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.
Structure of 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
Take the lead, don't take the lead
Cyclic and non cyclic
I will describe one-way headless acyclic list and two-way headless acyclic list. This article first talks about one-way headless acyclic list
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
2. Take the lead and not take the lead
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 public class SingleLinkedList { //Head insertion public void addFirst(int data); //Tail interpolation public void addLast(int data); //Insert at any position, and the first data node is subscript 0 public void addIndex(int index,int data); //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(){ while(head=null){ System.out.print(head.val+" "); head=head.next; } }
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(){ ListNode cur=head; while(cur=null){ System.out.print(cur.val+" "); cur=cur.next; } }
About head interpolation
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 public void addFirst(int data){ ListNode node=ListNode(data); if(head==null){ head=node; }else{ node.next=head; head=node; } }
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 public void addFirst(int data){ ListNode node=ListNode(data); node.next=head; head=node; }
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 public void addLast(int data) { ListNode node=new ListNode(data); if(head==null){ head=node; }else{ ListNode cur=head; 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() { ListNode cur=this.head; 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){ ListNode cur=head; 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){ addFirst(data); return; } if (index==size()){ addLast(data); 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) { ListNode cur=this.head; 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){ ListNode cur=this.head; 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) { if(this.head==null){ System.out.println("The linked list is empty!"); return; } if(this.head.val==key){ this.head=this.head.next; 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) { if(this.head==null) { return; } ListNode prev=this.head; ListNode cur=prev.next; while (cur!=null){ if(cur.val==key){ prev.next=cur.next; cur=cur.next; }else { prev=cur; cur=cur.next; } } if(this.head.val==key){ this.head=this.head.next; } }
Last emptying operation
The simplest operation is head=null.
The second method is, head=null, and then head=head.next; Until the end
public void clear(){ head=null; }
public void clear(){ while(head!=null){ ListNode headNext=head.next; head=null; head=headNext; } }