1.什么是链表?

链表(linked list)是一种在物理上非连续、非顺序的数据结构,由若干节点(node)所组成。
单向链表的每一个节点又包含两部分,一部分是存放数据的变量data,另一部分是指向下一个节点的指针next。
1. private static class Node {
2. int data;
3. Node next;
4. }
链表的第1个节点被称为头节点,最后1个节点被称为尾节点,尾节点的next指针指向空(NULL)。
2.什么是双向链表?
双向链表的每一个节点除了拥有data和next指针,还拥有指向前置节点的prev指针。

3.链表的存储方式


4.链表的基本操作
1. 查找节点 o(n)

2.更新节点

如果不考虑查找节点的过程,链表的更新过程会像数组那样简单,直接把旧数据替换成新数据即可。
3.插入节点 o(1)
- 尾部插入
把最后一个节点的next指针指向新插入的节点即可。

- 头部插入
第1步,把新节点的next指针指向原先的头节点。
第2步,把新节点变为链表的头节点。

- 中间插入
第1步,新节点的next指针,指向插入位置的节点。
第2步,插入位置前置节点的next指针,指向新节点。
只要内存空间允许,能够插入链表的元素是无穷无尽的,不需要像数组那样考虑扩容的问题。

4.删除节点 o(1)
- 尾部删除
把倒数第2个节点的next指针指向空即可

- 头部删除
把链表的头节点设为原先头节点的next指针即可

- 中间删除
把要删除节点的前置节点的next指针,指向要删除元素的下一个节点即可

1. // 头节点指针
2. private Node head;
3. // 尾节点指针
4. private Node last;
5. // 链表实际长度
6. private int size;
7.
8. /**
9. * 链表插入元素
10. * @param data 插入元素
11. * @param index 插入位置
12. */
13. public void insert(int data, int index) throws Exception {
14. if (index<0 || index>size) {
15. throw new IndexOutOfBoundsException(" 超出链表节点范围!");
16. }
17. Node insertedNode = new Node(data);
18. if(size == 0){
19. //空链表
20. head = insertedNode;
21. last = insertedNode;
22. } else if(index == 0){
23. //插入头部
24. insertedNode.next = head;
25. head = insertedNode;
26. }else if(size == index){
27. //插入尾部
28. last.next = insertedNode;
29. last = insertedNode;
30. }else {
31. //插入中间
32. Node prevNode = get(index-1);
33. insertedNode.next = prevNode.next;
34. prevNode.next = insertedNode;
35. }
36. size++;
37. }
38.
39. /**
40. * 链表删除元素
41. * @param index 删除的位置
42. */
43. public Node remove(int index) throws Exception {
44. if (index<0 || index>=size) {
45. throw new IndexOutOfBoundsException(" 超出链表节点范围!");
46. }
47. Node removedNode = null;
48. if(index == 0){
49. //删除头节点
50. removedNode = head;
51. head = head.next;
52. }else if(index == size-1){
53. //删除尾节点
54. Node prevNode = get(index-1);
55. removedNode = prevNode.next;
56. prevNode.next = null;
57. last = prevNode;
58. }else {
59. //删除中间节点
60. Node prevNode = get(index-1);
61. Node nextNode = prevNode.next.next;
62. removedNode = prevNode.next;
63. prevNode.next = nextNode;
64. }
65. size--;
66. return removedNode;
67. }
68.
69. /**
70. * 链表查找元素
71. * @param index 查找的位置
72. */
73. public Node get(int index) throws Exception {
74. if (index<0 || index>=size) {
75. throw new IndexOutOfBoundsException(" 超出链表节点范围!");
76. }
77. Node temp = head;
78. for(int i=0; i<index; i++){
79. temp = temp.next;
80. }
81. return temp;
82. }
83.
84. /**
85. * 输出链表
86. */
87. public void output(){
88. Node temp = head;
89. while (temp!=null) {
90. System.out.println(temp.data);
91. temp = temp.next;
92. }
93. }
94.
95. /**
96. * 链表节点
97. */
98. private static class Node {
99. int data;
100. Node next;
101. Node(int data) {
102. this.data = data;
103. }
104.}
105.
106.public static void main(String[] args) throws Exception {
107. MyLinkedList myLinkedList = new MyLinkedList();
108. myLinkedList.insert(3,0);
109. myLinkedList.insert(7,1);
110. myLinkedList.insert(9,2);
111. myLinkedList.insert(5,3);
112. myLinkedList.insert(6,1);
113. myLinkedList.remove(0);
114. myLinkedList.output();
115.}
本文介绍了链表(包括单向和双向链表)的概念,存储方式,以及基本操作如查找、插入和删除的时间复杂度分析。通过示例展示了如何在Java中实现链表并进行相关操作。
5万+






