1 concept and structure of linked list

Linked list is a discontinuous storage structure in physical storage structure. The logical order of data elements is realized through the reference link order in the linked list.

A linked list is composed of nodes. A node is divided into two parts (val and next). val is used to save data, which is called a data field, while next is used to save the address of the next node. The connection between nodes depends on next.

In practice, the structure of linked list is very diverse. There are eight linked list structures when the following situations are combined:

Unidirectional and bidirectional

Cyclic and non cyclic

Explanation of the structure of the linked list:

1 unidirectional and bidirectional

You can vaguely know from the name that one-way is that the whole linked list can only move in one direction

The so-called taking the lead and not taking the lead is whether there is a fixed head node in front of the linked list

If you don't take the lead, as long as the node is in the first position, it is the head node of the whole linked list, which can be changed.

If you take the lead, the head node always exists and the next always points to the first valid node.

3. Circulation and non circulation

Related code

```,Implementation of headless one-way acyclic linked list
//Tail interpolation
//Insert at any position, and the first data node is subscript 0
//Find out whether the keyword is included and whether the key is in the single linked list
public boolean contains(int key);
//Delete the node whose keyword is key for the first time
public void remove(int key);
//Delete all nodes with the value of key
public void removeAllKey(int key);
//Get the length of the single linked list
public int size();
public void display();
public void clear();
}```

preparation

Because the linked list is a reference type, we need to define a linked list class when using it

```class ListNode{
public int val; //data
public ListNode next;    //Address of the next node
public ListNode(int val){
this.val=val;
}
}```

At first, I may be confused. Why is the type of next ListNode? As the annotation says, next stores the address of the next node, and what type is each node!! ListNode type, so we declare a next of ListNode type to store the address of the next node.

A very important factor in all operations is the head node, so we need to create a head.

`public ListNode head;`

The preparation work is completed and various methods are implemented.

The first method to be implemented is the display method, because when writing other code, we need to output data to check whether there are running errors in the code we write.

dispaly() outputs the data in the linked list

When you think of traversal, the first thing you think of is a loop. Execute it once and output a data until the end of the loop.

Because the code we wrote today is "headless", we can cycle the head and shift the head to the next after output. The approximate code is as follows:

```public void dispaly(){
}

}
```

Are you happy when you finish writing, and you think you can write a code? In fact, it's not. Here, imagine whether the head has changed after we execute this method. How can we use the head to perform other operations? Therefore, we can't change the value of head. At this time, we can define a value to cycle instead of head, and finally output the replacement value. In this way, we can output the result without considering whether the head has changed. So it should be written as follows:

```public void dispaly(){
while(cur=null){
System.out.print(cur.val+" ");
cur=cur.next;
}

}```

As the name suggests, header insertion means that the position of each element added is the first position of the head of the linked list, so we need to have an existing linked list and insert it.

Case 1: when the head is null, it means that there is no data in the linked list. At this time, we can directly head=node.

Case 2: when the linked list has data

Step 1: the next node should point to the current head location address.

Step 2: assign the node address to the head, so that the node becomes a new head node.

The code is as follows:

``` //Head insertion
ListNode node=ListNode(data);
}else{
}
}```

The next of node is null and the location address of head is null. Therefore, it can be used without additional consideration.

The simpler code is as follows:

``` //Head insertion
ListNode node=ListNode(data);
}```

Tail interpolation

Tail interpolation method inserts data at the last position of the linked list. The next of the last position of a linked list points to null, so it is used as a loop condition.

Idea:

1 judge whether the head is empty. If the head is empty, we can assign a value directly.

2 if the head is not empty, we need to find the last node through the loop, and then add the new node.

code:

``` //Tail interpolation
ListNode node=new ListNode(data);
}else{
while(cur.next!=null){
cur=cur.next;
}
cur.next=node;
}

}
```

Get the length of the linked list

``` //Get the length of the single linked list
public int size() {
int count=0;
while (cur!=null){
cur=cur.next;
count++;
}
return count;
}```

Insert anywhere

The so-called arbitrary position is the head, tail and middle. We have written the head and tail, so we can call it directly. What needs to be considered is the middle insertion.

You can use a method to find the node address at index-1

```public ListNode findIndex(int index){
while(index-1!=0){
cur=cur.next;
index--;
}
return cur;
}```

Steps:

1. Judge whether the insertion position is legal

2 if the position is the beginning and end, it is called directly

3 insert according to the findIndex() method

```  //Insert at any position, and the first data node is subscript 0
public void addIndex(int index,int data) {
if(index<0||index>size()){
System.out.println("Illegal location!");
return;
}
if(index==0){
return;
}
if (index==size()){
return;
}
ListNode cur=findIndex(index);
ListNode node=new ListNode(data);
node.next=cur.next;
cur.next=node;
}```

Find out whether the keyword is included and whether the key is in the single linked list

First cycle the whole linked list, and then judge whether there are keywords in the single linked list. If they are not found at the end of the cycle, false will be returned

```    //Find out whether the keyword is included and whether the key is in the single linked list
public boolean contains(int key) {
while (cur!=null){
if(cur.val==key){
return true;
}
cur=cur.next;
}
return  false;
}```

Delete the node whose keyword is key for the first time

To delete, you need to judge whether the linked list is empty. If the linked list is empty, everything is unnecessary. The returned linked list is empty.

If the header node is the data to be deleted, we can delete it directly.

In other cases, you need to find the precursor of the keyword node and then delete it.

Find keyword precursor operation

``` public ListNode findPerv(int key){
while (cur.next!=null){
if (cur.next.val==key){
return cur;
}
cur=cur.next;
}
return null;
}```
``` //Delete the node whose keyword is key for the first time
public void remove(int key) {
return;
}
return;
}
ListNode cur=findPerv(key);
if(cur==null){
System.out.println("There is no data to delete!");
return;
}
ListNode del=cur.next;
cur.next=del.next;
}```

Delete all nodes with the value of key

Delete all key s, first judge whether the head is empty, then use the loop to judge, and define two variables prve and cur, cur=prve.next;

prve is used to establish the connection of the linked list. cur is used to determine the key value and delete it

After looping through all, you will find that the first head position is not judged. This is the last step to judge whether head.val is a key and delete it.

``` //Delete all nodes with the value of key
public void removeAllKey(int key) {
return;
}
ListNode cur=prev.next;
while (cur!=null){
if(cur.val==key){
prev.next=cur.next;
cur=cur.next;
}else {
prev=cur;
cur=cur.next;
}
}
}

}```

Last emptying operation

```public void clear(){
```public void clear(){