Linked list and its basic operations (Java language version)

1. Linked list

Linked list (Linked list) is a common basic data structure. It is a linear list, but it does not store data in a linear order, but stores a pointer (Pointer) to the next node in each node. Since it does not have to be stored in order, the linked list can reach the complexity of O(1) when inserting, which is much faster than another linear list sequence table, but it takes O(n) to find a node or access a specific numbered node time, and the corresponding time complexities of sequence table are O(logn) and O(1) respectively.

1. Singly linked list

Singly linked list, which contains two fields, an information field and a pointer field. The information field is used to store the value to be stored in the linked list, and the pointer field points to the next node. This link points to the next node in the list, and the last node points to a null value. Its structure diagram is as follows:
insert image description here

2. Doubly linked list

On the basis of the single linked list, the doubly linked list adds a pointer field to each node to point to the previous node. Its structure diagram is as follows:
insert image description here

Second, the basic operation of the linked list

First create a LinkedList class.

0. The object of the linked list node

Create a ListNode class that contains two properties, one is the value of the linked list node, and the other is the address of the next node.
Create a size attribute to record the length of the linked list

public class LinkedList {
    
    

	//定义节点
	static class ListNode {
    
    
		int val; // 链表存储的值
		ListNode next; // 指针,指向下一个节点
		ListNode() {
    
    
			
		}
		ListNode(int val) {
    
     
			this.val = val; 
		}
		ListNode(int val, ListNode next) {
    
     
			this.val = val;
			this.next = next; 
		}
	}
	
	int size; // 链表长度
	ListNode headNode; //链表头结点
	ListNode dummyHead = new ListNode(0);
}

1. Head insertion method

Head insertion method, that is, adding a node at the head of the linked list as a new head node.
First create a ListNode object as the node to be inserted, and then operate according to the situation. If the current linked list is an empty linked list, a linked list can be created by directly using the node as the head node; if the current linked list is not an empty linked list, the next pointer of the node to be inserted points to the original head node.

	public void headInsertion(int val) {
    
    
		ListNode newListNode = new ListNode(); // 新建一个对象,即为要插入的节点
		newListNode.val = val; // 对节点存入要插入的值
		if (headNode == null) {
    
     //头结点为空即是个空链表,头结点直接指向要插入的节点即可
			headNode = newListNode;
		} else {
    
    
			newListNode.next = headNode; // 要插入的节点应放在第一个,所以它的下一个节点指向head
			headNode = newListNode; // 插入后新插入的节点是新的头结点
		}
		size ++;
	}

2. Insert a node at any position

The insert method is to insert a node at any position. The index in the parameter is the position of the inserted node, and val is the value of the inserted node. If the index is equal to 0, the process is the same as the head insertion method. Otherwise, it is necessary to find the previous node first, point the next pointer of this node to the node pointed to by the previous node next, and then point the previous node to this node.
The insertion process diagram is as follows:
(1) Create the node object to be inserted
insert image description here
(2) The current node points to the next node
insert image description here
(3) The previous node points to the current node to complete the insertion
insert image description here

	public void insert(int index, int val) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode newListNode = new ListNode(); // 存放添加元素的链表节点
		newListNode.val = val;
		if (index == 0) {
    
     // 插入到第0位,和头插法相同
			if (headNode == null) {
    
    
				headNode = newListNode;
			} else {
    
    
				newListNode.next = headNode;
				headNode = newListNode;
			}
			size ++;		
		} else {
    
    
			ListNode prevNode = headNode; // 创建一个指向头结点的指针
			for (int i = 0; i < index-1; i++) {
    
    
				prevNode = prevNode.next; // 用该指针找到要添加元素位置的前一个
			}
			newListNode.next = prevNode.next; // 添加的节点的next指针指向要添加位置的下一个
			prevNode.next = newListNode; //前一个节点的next指针指向添加的节点
			size ++;
		}
	}

3. Tail plugging method

First find the original last node, and then point its next to the node to be inserted.

	public void tailInsertion(int val) {
    
    
		ListNode newListNode = new ListNode();
		newListNode.val = val; 
		ListNode prevNode = headNode; // 创建一个指向头结点的指针
		for (int i = 0; i < size-1; i++) {
    
    
			prevNode = prevNode.next;// 用该指针找到要最后一个节点的前一个节点
		}
		newListNode.next = prevNode.next;
		prevNode.next = newListNode;
		size ++;
	}

4. Delete the index element

Find the index-1 node and point it directly to the index+1 node. Need to pay attention to empty linked list or out of bounds.
The deletion process diagram is as follows:
(1) Find the current node object to be deleted
insert image description here
(2) The previous pointer points to the next node to delete.
insert image description here

	public void deleteByIndex(int index) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		if (headNode == null) {
    
    
			System.out.println("空链表");
		} else {
    
    
			if (index == 0) {
    
     // 删除第一个元素,直接把头结点指向第二个元素即可
				headNode = headNode.next;
				size --;
			} else {
    
    
				ListNode prevNode = headNode; // 创建一个指向头结点的指针
				for (int i = 0; i < index-1; i++) {
    
    
					prevNode = prevNode.next; // 用该指针找到要删除元素位置的前一个
				}
				System.out.println("delete:"+prevNode.next.val);
				// 要删除的元素的前一个节点的next指针指向下一个节点,完成删除
				prevNode.next = prevNode.next.next; 
				size --;
			}
		}
	}

5. Delete the val element

Delete the node whose value is val, and traverse to find the node whose value is val, and delete it.

	public void deleteByValue(int val) {
    
    
		if (headNode == null) {
    
    
			System.out.println("空链表");
		} else {
    
    
			while(val == headNode.val){
    
    // 如果头结点是要删除的元素
				headNode = headNode.next;
				size --;
			}
			ListNode prevNode = headNode; // 创建指针,指向被操作的节点的前一位
			ListNode currentNode = headNode; // 创建指针,指向被操作的节点
			while(prevNode != null && currentNode != null){
    
    
				if(currentNode.val == val) {
    
    
					prevNode.next = currentNode.next;
					size--;
				} else {
    
    
					prevNode = currentNode;
				}
				currentNode = currentNode.next;
			}
		}
	}

6. Get the value of the index node

You can find it by traversing.

	public void getElum(int index) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode currentNode = headNode;
		for (int i = 0; i < index; i++) {
    
    
			currentNode = currentNode.next;
		}
		int result = currentNode.val;
		System.out.println(result);
	}

7. Change the value of the Index node to val

Find the index node and modify val.

	public void update(int index, int val) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode currentNode = headNode;
		for (int i = 0; i < index; i++) {
    
    
			currentNode = currentNode.next;
		}
		currentNode.val = val;
	}

8. Create a linked list

	// 创建一个链表  1->2
	public void creatLinkList() {
    
    
		ListNode node1 = new ListNode();
		node1.val = 2;
		ListNode node2 = new ListNode();
		node2.val = 1;
		node1.next = node2;
		headNode = node1;
		size++;
		size++;
	}

9. Print the linked list in order

	public void display(){
    
    
		ListNode current = headNode;
		while(current != null){
    
    
			System.out.print(current.val);
			if (current.next != null) {
    
    
				System.out.print("->");
			}
			current = current.next;
		}
		System.out.println();
	}

3. Final code display (including testing)

package linkedList;

public class SingleLinkedList {
    
    

	//定义节点
	static class ListNode {
    
    
		int val; // 链表存储的值
		ListNode next; // 指针,指向下一个节点
		ListNode() {
    
    
			
		}
		ListNode(int val) {
    
     
			this.val = val; 
		}
		ListNode(int val, ListNode next) {
    
     
			this.val = val;
			this.next = next; 
		}
	}
	
	int size; // 链表长度
	ListNode headNode; //链表头结点
//	ListNode dummyHead = new ListNode(0);
	public SingleLinkedList() {
    
    
		headNode = null;
		size = 0;
	}
	
	//头插法
	public void headInsertion(int val) {
    
    
		ListNode newListNode = new ListNode(); // 新建一个对象,即为要插入的节点
		newListNode.val = val; // 对节点存入要插入的值
		if (headNode == null) {
    
     //头结点为空即是个空链表,头结点直接指向要插入的节点即可
			headNode = newListNode;
		} else {
    
    
			newListNode.next = headNode; // 要插入的节点应放在第一个,所以它的下一个节点指向head
			headNode = newListNode; // 插入后新插入的节点是新的头结点
		}
		size ++;
	}
	
	//头插法(使用虚拟头结点的方法)
//	public void headInsertionVirtual(int val) {
    
    
//		ListNode dummyHead = new ListNode(0, this.head);
//		ListNode newListNode = new ListNode();
//		newListNode.val = val;
//		ListNode currentNode = dummyHead;
//		currentNode.val = val;
//		currentNode.next = dummyHead.next;
//		size ++;
//	}
	
	//任意位置插入
	public void insert(int index, int val) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode newListNode = new ListNode(); // 存放添加元素的链表节点
		newListNode.val = val;
		if (index == 0) {
    
     // 插入到第0位,和头插法相同
			if (headNode == null) {
    
    
				headNode = newListNode;
			} else {
    
    
				newListNode.next = headNode;
				headNode = newListNode;
			}
			size ++;		
		} else {
    
    
			ListNode prevNode = headNode; // 创建一个指向头结点的指针
			for (int i = 0; i < index-1; i++) {
    
    
				prevNode = prevNode.next; // 用该指针找到要添加元素位置的前一个
			}
			newListNode.next = prevNode.next; // 添加的节点的next指针指向要添加位置的下一个
			prevNode.next = newListNode; //前一个节点的next指针指向添加的节点
			size ++;
		}
	}
	
	//尾插法
	public void tailInsertion(int val) {
    
    
		ListNode newListNode = new ListNode();
		newListNode.val = val; 
		ListNode prevNode = headNode; // 创建一个指向头结点的指针
		for (int i = 0; i < size-1; i++) {
    
    
			prevNode = prevNode.next;// 用该指针找到要最后一个节点的前一个节点
		}
		newListNode.next = prevNode.next;
		prevNode.next = newListNode;
		size ++;
	}
	
	//删除第index个元素
	public void deleteByIndex(int index) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		if (headNode == null) {
    
    
			System.out.println("空链表");
		} else {
    
    
			if (index == 0) {
    
     // 删除第一个元素,直接把头结点指向第二个元素即可
				headNode = headNode.next;
				size --;
			} else {
    
    
				ListNode prevNode = headNode; // 创建一个指向头结点的指针
				for (int i = 0; i < index-1; i++) {
    
    
					prevNode = prevNode.next; // 用该指针找到要删除元素位置的前一个
				}
				System.out.println("delete:"+prevNode.next.val);
				// 要删除的元素的前一个节点的next指针指向下一个节点,完成删除
				prevNode.next = prevNode.next.next; 
				size --;
			}
		}
	}
	
	//删除val元素
	public void deleteByValue(int val) {
    
    
		if (headNode == null) {
    
    
			System.out.println("空链表");
		} else {
    
    
			while(val == headNode.val){
    
    // 如果头结点是要删除的元素
				headNode = headNode.next;
				size --;
			}
			ListNode prevNode = headNode; // 创建指针,指向被操作的节点的前一位
			ListNode currentNode = headNode; // 创建指针,指向被操作的节点
			while(prevNode != null && currentNode != null){
    
    
				if(currentNode.val == val) {
    
    
					prevNode.next = currentNode.next;
					size--;
				} else {
    
    
					prevNode = currentNode;
				}
				currentNode = currentNode.next;
			}
		}
	}
	
	public void getElum(int index) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode currentNode = headNode;
		for (int i = 0; i < index; i++) {
    
    
			currentNode = currentNode.next;
		}
		int result = currentNode.val;
		System.out.println(result);
	}
	
	public void update(int index, int val) {
    
    
		if (index > size) {
    
    
			System.out.println("越界");
			return;
		}
		ListNode currentNode = headNode;
		for (int i = 0; i < index; i++) {
    
    
			currentNode = currentNode.next;
		}
		currentNode.val = val;
	}
	
	// 创建一个链表  1->2
	public void creatLinkList() {
    
    
		ListNode node1 = new ListNode();
		node1.val = 2;
		ListNode node2 = new ListNode();
		node2.val = 1;
		node1.next = node2;
		headNode = node1;
		size++;
		size++;
	}
	
	
	//打印链表
	public void display(){
    
    
		ListNode current = headNode;
		while(current != null){
    
    
			System.out.print(current.val);
			if (current.next != null) {
    
    
				System.out.print("->");
			}
			current = current.next;
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
    
    
		SingleLinkedList singleLinkedList = new SingleLinkedList();

		singleLinkedList.creatLinkList();
		singleLinkedList.headInsertion(5);
		singleLinkedList.headInsertion(8);
		singleLinkedList.headInsertion(9);
		singleLinkedList.headInsertion(5);
		singleLinkedList.display();
		
		singleLinkedList.insert(0,3);
		singleLinkedList.insert(0,3);
		singleLinkedList.insert(2,3);
		singleLinkedList.insert(2,3);
		singleLinkedList.insert(2,7);
		singleLinkedList.display();
		
		singleLinkedList.tailInsertion(1);
		singleLinkedList.display();
		
		singleLinkedList.deleteByIndex(1);
		singleLinkedList.display();
		
		singleLinkedList.deleteByValue(3);
		singleLinkedList.display();
		singleLinkedList.getElum(0);

		singleLinkedList.update(1, 6);
		singleLinkedList.display();
	}
}

Guess you like

Origin blog.csdn.net/qq_43647936/article/details/131935412