单链表的插入,查找,删除
链表是一种重要的数据结构,相比于数组,数组更像是一个顺序表,数组只要第一个元素固定,那么在他后面的元素的地址一定固定,数组在内存中是一块连续的存储区域,我们可以根据下标找到他的每个元素,这是数组和链表的一个区别
链表,见名思意,一个链子连接起来的表,元素之间的联系靠的是这个链子,这也决定了链表中的每个元素不是连续的,第一个元素在内存中的一个地方,而下一个元素可以在离他很远的地方,他们之间有一个链子连接着,这个链子准确来说是指针,第一个元素指向第二个,依次指向下去,我们对某个元素进行操作的时候,我们只能从头依次查找找到这个元素再进行操作。单链表是指单向的链表,我们只能从他的头向后查找,而双向链表,不光可以从头部向后查找,也可以从后向前查找。
数组的查找,更改方便,而数组的增加,删除方便。数组可以根据下标找到元素,而链表只能从头部依次向后查找,相比于数组的增加,删除操作会涉及到元素的移动,链表就方便很多,我们只需要把他前后的指向的元素改变一下,就可以实现元素的增加和删除。
对链表的操作也是很基本的操作,下面只是对单链表的操作
定义一个节点类,定义他的数据域,和next指针(不能说是一个指针,他是下一个元素,指针更好理解)
package demo_linkedlist; public class Node { public int element; // public Node pre; public Node next; public Node(){ } // public Node(int element,Node pre,Node next){ // this.element=element; // this.pre=pre; // this.next=next; // } public Node(int element,Node next){ this.element=element; this.next=next; } @Override public String toString() { return element + "->"+next; } }
在定义节点的时候,定义了一个head头节点,头节点始终指向链表中的第一个元素。这样对链表中的第一个数据进行操作的时候,可以方便些
一个节点的初始化方法,为什么倒过来定义,因为在定义指向下一个元素的next指针的时候是先定义前一个元素的next指向,然而后一个节点还没有定义,倒过来就解决了。
private Node n10 = null; private Node n8 = null; private Node n7 = null; private Node n6 = null; private Node n5 = null; private Node n4 = null; private Node n3 = null; private Node n2 = null; private Node n1 = null; private Node head = null; public void init() { n10 = new Node(10, null); n8 = new Node(8, n10); n7 = new Node(7, n8); n6 = new Node(6, n7); n5 = new Node(5, n6); n4 = new Node(4, n5); n3 = new Node(3, n4); n2 = new Node(2, n3); n1 = new Node(1, n2); head = new Node(0, n1); }
遍历节点方法
/** * 打印每个节点的值 */ public void print() { Node star = head; while (star != null) { System.out.print(star.element + " "); star = star.next; } System.out.println(); }
查找结点值为a的某个节点
/** * 查找结点的值 */ public Node find(int a) { Node current = n1; while (current.element != a) { if (current.next == null) { return null; } current = current.next; } return current; }
插入节点,这时候头节点head的作用就用上了,当插入节点值小于链表中的任何元素的时候,为了保证链表的有序,只需要改变头节点的指向就可以
/** * 插入一个节点,并保证链表依然有序 */ public Node insert(int a) { Node n9 = new Node(a, null); Node current = head; while (current.next != null) { if (a < current.element) { n9.next = current; current.next = n9; break; } if (current.element <= a && current.next.element > a) { n9.next = current.next; current.next = n9; break; } current = current.next; } if (current.element < a && current.next == null) { n9.next = null; current.next = n9; } return current; }
删除某个节点的方法,由于单链表的特点,我们只能从前向后查找,这样当我们找到要删除的节点的时候,由于前一个节点已经过去了,所以我们只能获得后一个节点,改变不了前一个节点的指向,解决的办法就是只需要定义两个节点,一个指向前一个,另一个指向后一个,每次遍历的时候这两个节点依次向后移动,当找到要操作的节点的时候,由于我们已经记录了前一个节点,这样只需要见到的改变一下指向即可。
/** * 删除值为a的节点 */ public Node delete(int a) { Node current = head; Node current1 = head.next; while (current1.next != null) { if (current1.element == a) { current.next = current1.next; return current; } current = current.next; current1 = current1.next; } if (current1.next == null) { current.next = null; } return current; }
完整代码:
package demo_linkedlist; /** * 在链表中定义了一个head头节点,时钟在链表的头部,在执行插入操作的时候会方便些 * */ public class LinkedLists { private Node n10 = null; private Node n8 = null; private Node n7 = null; private Node n6 = null; private Node n5 = null; private Node n4 = null; private Node n3 = null; private Node n2 = null; private Node n1 = null; private Node head = null; public void init() { n10 = new Node(10, null); n8 = new Node(8, n10); n7 = new Node(7, n8); n6 = new Node(6, n7); n5 = new Node(5, n6); n4 = new Node(4, n5); n3 = new Node(3, n4); n2 = new Node(2, n3); n1 = new Node(1, n2); head = new Node(0, n1); } public static void main(String[] args) { LinkedLists l = new LinkedLists(); l.init(); l.print();// 遍历链表 System.out.println("查找:" + l.find(6)); l.insert(11); System.out.println("插入数据后:" + l.head); l.delete(11); System.out.println("删除后:" + l.head); } /** * 打印每个节点的值 */ public void print() { Node star = head; while (star != null) { System.out.print(star.element + " "); star = star.next; } System.out.println(); } /** * 查找结点的值 */ public Node find(int a) { Node current = n1; while (current.element != a) { if (current.next == null) { return null; } current = current.next; } return current; } /** * 插入一个节点,并保证链表依然有序 */ public Node insert(int a) { Node n9 = new Node(a, null); Node current = head; while (current.next != null) { if (a < current.element) { n9.next = current; current.next = n9; break; } if (current.element <= a && current.next.element > a) { n9.next = current.next; current.next = n9; break; } current = current.next; } if (current.element < a && current.next == null) { n9.next = null; current.next = n9; } return current; } /** * 删除值为a的节点 */ public Node delete(int a) { Node current = head; Node current1 = head.next; while (current1.next != null) { if (current1.element == a) { current.next = current1.next; return current; } current = current.next; current1 = current1.next; } if (current1.next == null) { current.next = null; } return current; } }
如有不对的地方欢迎指正!