1 package zz;
2
3 import java.util.Stack;
4
5 /**
6 *
7 * @author zz
8 * 关于java中链表的操作
9 * 0. 向链表中插入新节点
10 * 1. 求单链表中结点的个数: getListLength
11 * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
12 * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
13 * 4. 查找单链表的中间结点: getMiddleNode
14 * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
15 * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
16 * 7. 对链表的后半部分进行反转。reversePartNode
17 * 8. 判断单链表是否存在环,isLoop。 使用两个指针,fast和low,fast一次走两步,low一次走一步。若存在环,总会有某个时刻fast和low指向同一节点
18 * 9. 求出环的长度。getLoopLength().记录8中fast和low的遭遇点。然后让low走一圈环记数即可
19 * 10. 对单链表进行排序,listSort(归并),insertionSortList(插入)
20 * // 注释部分代码也经过调试正确
21 */
22 public class LinkedListSummary {
23 public static class Node {
24 int data;
25 Node next;
26 public Node(int value) {
27 data = value;
28 next = null;
29 }
30 }
31 //向链表中插入新节点
32 public static void addNode(Node head, int data) {
33 Node newNode = new Node(data);
34 if(head == null) {
35 head = newNode;
36 return;
37 } else {
38 Node temp = head;
39 while(temp.next != null) {
40 temp = temp.next;
41 }
42 temp.next = newNode;
43 }
44 }
45 //输出链表的长度
46 public static int getListLength(Node head) {
47 int len = 0;
48 //if(head == null) return 0;
49 Node temp = head;
50 while(temp != null) {
51 len++;
52 temp = temp.next;
53 }
54 System.out.println("输出链表长度:" + len);
55 return len;
56 }
57 //顺序打印链表数据
58 public static void print(Node head) {
59 if(head == null) {
60 System.out.println("链表为空");
61 return;
62 }
63 Node temp = head;
64 while(temp != null) {
65 System.out.print(temp.data + " ");
66 temp = temp.next;
67 }
68 }
69 //方法1:使用栈反向遍历单链表
70 public static void reversePrint(Node head) {
71 if(head == null || head.next == null) return;
72 Stack<Node> nodes = new Stack<Node>();
73 Node temp = head;
74 while(temp != null) {
75 nodes.push(temp);
76 temp = temp.next;
77 }
78 while(!nodes.isEmpty()) {
79 //nodes.pop();
80 System.out.print(nodes.pop().data + " ");
81 }
82 }
83 //方法二:反向遍历单链表
84 public static Node reversePrint2(Node head) {
85 if(head == null || head.next == null) return head;
86 Node pre = null;
87 Node temp = null;
88 while(head != null) {
89 temp = head.next;
90 head.next = pre;
91 pre = head;
92 head = temp;
93 }
94 print(pre);
95 // System.out.println(head == null ? "空" : "非空");
96 return pre;
97 }
98 //递归反向遍历单链表
99 public static Node reversePrintRec(Node head) {
100 if(head == null || head.next == null) {
101 System.out.println("链表遍历完成,只有head节点或为空链表");
102 return head;
103 }
104 Node reHead = reversePrintRec(head.next);
105 head.next.next = head;
106 head.next = null;
107 return head;
108 }
109 //从尾到头打印递归打印单链表
110 public static void reversePrintListRec(Node head) {
111 if(head == null) {
112 return;
113 } else {
114 reversePrintListRec(head.next);
115 System.out.print(head.data + ",");
116 }
117 }
118 //查找单链表的倒数第K个节点(k>0)
119 public static Node reGetKthNode(Node head, int k) {
120 int len = 0;
121 Node temp = head;
122 while(temp != null) {
123 len++;
124 temp = temp.next;
125 }
126 if(k > len) {
127 System.out.println("链表长度有限,小于K,找不到倒数第K个节点");
128 return null;
129 }
130 Node n1 = head;
131 Node n2 = head;
132 for(int i = 0; i < k; i++) {
133 n1 = n1.next;
134 }
135 while(n1 != null){
136 n2 = n2.next;
137 n1 = n1.next;
138 }
139 System.out.println(n2.data);
140 return n2;
141 }
142 //查找单链表的中间结点: getMiddleNode
143 public static Node getMiddleNode(Node head) {
144 if(head == null || head.next == null) return head;
145 Node n1 = head;
146 Node n2 = head;
147 while(n2 != null && n2.next != null) {
148 n1 = n1.next;
149 n2 = n2.next.next;
150 }
151 //System.out.println(n1.data);
152 return n1;
153 }
154 //已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList
155 public static Node mergeSortedList(Node head1, Node head2) {
156 if(head1 == null) return head2;
157 if(head2 == null) return head1;
158 Node target = null;
159 if(head1.data > head2.data) {
160 target = head2;
161 head2 = head2.next;
162 } else {
163 target = head1;
164 head1 = head1.next;
165 }
166 target.next = null;
167 Node newHead = target;
168 while(head1 != null && head2 != null) {
169 if(head1.data > head2.data) {
170 target.next = head2;
171 head2 = head2.next;
172 } else {
173 target.next = head1;
174 head1 = head1.next;
175 }
176 target = target.next;
177 target.next = null;
178 }
179 if(head1 == null) {
180 target.next = head2;
181 } else {
182 target.next = head1;
183 }
184 return newHead;
185 }
186 //已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序(递归实现): mergeSortedListRec
187 public static Node mergeSortedListRec(Node head1, Node head2) {
188 if(head1 == null) return head2;
189 if(head2 == null) return head1;
190 Node head = null;
191 if(head1.data > head2.data) {
192 head = head2;
193 head.next = mergeSortedListRec(head2.next, head1);
194 } else {
195 head = head1;
196 head.next = mergeSortedListRec(head1.next, head2);
197 }
198 return head;
199 }
200 //将链表的后半部分进行反转
201 public static Node reversePartNode(Node head){
202 Node flag = head;
203 Node cur = null;
204 Node mid = getMiddleNode(head);
205
206 while(flag.next != mid) { //取出中间节点的 前一个节点并保存
207 flag = flag.next;
208 }
209 Node pre = null;
210 //System.out.println("----" + flag.data);
211 while(mid != null) {
212 cur = mid.next;
213 mid.next = pre;
214 pre = mid;
215 mid = cur;
216 }
217
218 flag.next = pre;
219 print(head);
220
221 return head;
222 }
223 //判断链表是否存在环
224 public static boolean isLoop(Node head) {
225 if(head == null || head.next != null) return false;
226 Node fast = head;
227 Node low = head;
228 while(fast != null && fast.next != null) {
229 low = low.next;
230 fast = fast.next.next;
231 if(fast == low) break;
232 }
233 if(fast == null || fast.next == null) return false;
234 return true;
235 }
236 //求出环的长度
237 public static int getLoopLength(Node head) {
238 if(head == null || head.next != null) return 0;
239 Node fast = head;
240 Node low = head;
241 while(fast != null && fast.next != null) {
242 low = low.next;
243 fast = fast.next.next;
244 if(fast == low) break;
245 }
246 if(fast == null || fast.next == null) return 0;
247 else {
248 int loopLen = 1;
249 while(low.next != fast) {
250 loopLen++;
251 low = low.next;
252 }
253 return loopLen;
254 }
255
256 }
257 /*
258 //单链表排序
259 public static Node listSort(Node head) {
260 Node nex = null;
261 if(head == null || head.next == null) return head;
262 else if(head.next.next == null) {
263 nex = head.next;
264 head.next = null;
265 } else {
266 Node mid = getMiddleNode(head);
267 nex = mid.next;
268 mid.next = null;
269 }
270 print(mergeSortedList(listSort(head), listSort(nex)));
271 return mergeSortedList(listSort(head), listSort(nex));
272 }
273 */
274 public static void main(String[] args) {
275 Node head = new Node(0);
276 addNode(head, 6);
277 addNode(head, 2);
278 addNode(head, 1);
279 addNode(head, 4);
280 addNode(head, 3);
281 addNode(head, 5);
282 // listSort(head);
283 System.out.println("顺序打印链表数据:");
284 print(head);
285 System.out.println();
286 System.out.println("反转单链表后半部分节点:");
287 reversePartNode(head);
288 System.out.println();
289
290 if(isLoop(head)) {
291 System.out.println("存在环");
292 } else System.out.println("不存在环");
293
294 Node head1 = new Node(10);
295 addNode(head1, 11);
296 addNode(head1, 12);
297 addNode(head1, 13);
298 addNode(head1, 14);
299 addNode(head1, 15);
300 addNode(head1, 16);
301 addNode(head1, 17);
302 addNode(head1, 18);
303 addNode(head1, 19);
304 addNode(head1, 20);
305 /*
306 System.out.println();
307 System.out.println("反转单链表后半部分节点:");
308 reversePartNode(head1);
309 System.out.println();
310 */
311 Node head2 = new Node(100);
312 for(int i = 0; i < 8; i++) {
313 addNode(head2, 100+i);
314 }
315
316 Node head3 = new Node(1000);
317 for(int i = 0; i < 8; i++) {
318 addNode(head3, 1001+i);
319 }
320
321 getListLength(head);
322 System.out.println("顺序打印链表数据:");
323 print(head);
324 /*
325 // System.out.println();
326 // System.out.println("使用栈反转链表:");
327 // reversePrint(head);
328 // System.out.println();
329 // reversePrint2(head);
330 // System.out.println();
331 // System.out.println("递归反向遍历单链表");
332 // System.out.println("----" + head.data);
333 // reversePrintListRec(head);
334 // System.out.println();
335 // System.out.println("查找单链表的倒数第K个节点的值");
336 // reGetKthNode(head, 3);
337 // System.out.println();
338 // System.out.println("查找单链表的中间节点的值");
339 // getMiddleNode(head);
340 // System.out.println();
341 // System.out.println("合并两个单链表:");
342 // Node mergeHead = mergeSortedList(head, head1);
343 // print(mergeHead);
344 // System.out.println();
345 // System.out.println("递归实现合并两个单链表:");
346 // Node mergeHeadRec = mergeSortedListRec(head2, head3);
347 // print(mergeHeadRec);
348 */
349 }
350 }