01.import java.util.HashMap;
02.import java.util.Scanner;
03.import java.util.Stack;
04.
05./**
06. *
07. * @author kerryfish
08. * 关于java中链表的操作
09. * 1. 求单链表中结点的个数: getListLength
10. * 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
11. * 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
12. * 4. 查找单链表的中间结点: getMiddleNode
13. * 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
14. * 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
15. * 7. 对单链表进行排序,listSort(归并),insertionSortList(插入)
16. * 8. 判断一个单链表中是否有环: hasCycle
17. * 9. 判断两个单链表是否相交: isIntersect
18. * 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap
19. * 11. 给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete: deleteNode
20. */
21.public class LinkedListSummary {
22. /**
23. * @param args
24. *
25. */
26. public static class Node{
27. int value;
28. Node next;
29. public Node(int n){
30. this.value=n;
31. this.next=null;
32. }
33. }
34. public static void main(String[] args) {
35. // TODO Auto-generated method stub
36. Scanner in=new Scanner(System.in);
37. Node head=null;
38. if(in.hasNextInt()){
39. head=new Node(in.nextInt());
40. }
41. Node temp=head;
42. while(in.hasNextInt()){
43. temp.next=new Node(in.nextInt());
44. temp=temp.next;
45. }
46. in.close();
47. //int len=getListLength(head);
48. //Node reHead=reverseList(head);
49. //reHead=reverseListRec(reHead);
50. //Node node_k=reGetKthNode(head,3);
51. //Node mid=getMiddleNode(head);
52. //reversePrintListRec(head);
53. //reversePrintListStack(head);
54. //Node mergeHead=mergeSortedList(head,null);
55. //Node sortHead=listSort(head);
56.
57. }
58. //求单链表中结点的个数: getListLength
59. public static int getListLength(Node head){
60. int len=0;
61. while(head!=null){
62. len++;
63. head=head.next;
64. }
65. return len;
66. }
67. //将单链表反转,循环
68. public static Node reverseList(Node head){
69. if(head==null||head.next==null)return head;
70. Node pre=null;
71. Node nex=null;
72. while(head!=null){
73. nex=head.next;
74. head.next=pre;
75. pre=head;
76. head=nex;
77. }
78. return pre;
79. }
80. //将单链表反转,递归
81. public static Node reverseListRec(Node head){
82. if(head==null||head.next==null)return head;
83. Node reHead=reverseListRec(head.next);
84. head.next.next=head;
85. head.next=null;
86. return reHead;
87. }
88. //查找单链表中的倒数第K个结点(k > 0)
89. public static Node reGetKthNode(Node head,int k){
90. if(head==null)return head;
91. int len=getListLength(head);
92. if(k>len)return null;
93. Node target=head;
94. Node nexk=head;
95. for(int i=0;i<k;i++){
96. nexk=nexk.next;
97. }
98. while(nexk!=null){
99. target=target.next;
100. nexk=nexk.next;
101. }
102. return target;
103. }
104. //查找单链表的中间结点
105. public static Node getMiddleNode(Node head){
106. if(head==null||head.next==null)return head;
107. Node target=head;
108. Node temp=head;
109. while(temp!=null&&temp.next!=null){
110. target=target.next;
111. temp=temp.next.next;
112. }
113. return target;
114. }
115. //从尾到头打印单链表,递归
116. public static void reversePrintListRec(Node head){
117. if(head==null)return;
118. else{
119. reversePrintListRec(head.next);
120. System.out.println(head.value);
121. }
122. }
123. //从尾到头打印单链表,栈
124. public static void reversePrintListStack(Node head){
125. Stack<Node> s=new Stack<Node>();
126. while(head!=null){
127. s.push(head);
128. head=head.next;
129. }
130. while(!s.isEmpty()){
131. System.out.println(s.pop().value);
132. }
133. }
134. //合并两个有序的单链表head1和head2,循环
135. public static Node mergeSortedList(Node head1,Node head2){
136. if(head1==null)return head2;
137. if(head2==null)return head1;
138. Node target=null;
139. if(head1.value>head2.value){
140. target=head2;
141. head2=head2.next;
142. }
143. else{
144. target=head1;
145. head1=head1.next;
146. }
147. target.next=null;
148. Node mergeHead=target;
149. while(head1!=null && head2!=null){
150. if(head1.value>head2.value){
151. target.next=head2;
152. head2=head2.next;
153. }
154. else{
155. target.next=head1;
156. head1=head1.next;
157. }
158. target=target.next;
159. target.next=null;
160. }
161. if(head1==null)target.next=head2;
162. else target.next=head1;
163. return mergeHead;
164. }
165. //合并两个有序的单链表head1和head2,递归
166. public static Node mergeSortedListRec(Node head1,Node head2){
167. if(head1==null)return head2;
168. if(head2==null)return head1;
169. if(head1.value>head2.value){
170. head2.next=mergeSortedListRec(head2.next,head1);
171. return head2;
172. }
173. else{
174. head1.next=mergeSortedListRec(head1.next,head2);
175. return head1;
176. }
177. }
178. //对单链表进行排序,归并排序,在排序里面不建议选用递归的合并有序链表算法,如果链表长度较长,很容易出现栈溢出
179. public static Node listSort(Node head){
180. Node nex=null;
181. if(head==null||head.next==null)return head;
182. else if(head.next.next==null){
183. nex=head.next;
184. head.next=null;
185. }
186. else{
187. Node mid=getMiddleNode(head);
188. nex=mid.next;
189. mid.next=null;
190. }
191. return mergeSortedList(listSort(head),listSort(nex));//合并两个有序链表,不建议递归
192. }
193. //对单链表进行排序,插入排序
194. public Node insertionSortList(Node head) {
195. if(head==null||head.next==null)return head;
196. Node pnex=head.next;
197. Node pnex_nex=null;
198. head.next=null;
199. while(pnex!=null){
200. pnex_nex=pnex.next;
201. Node temp=head;
202. Node temp_pre=null;
203. while(temp!=null){
204. if(temp.value>pnex.value)break;
205. temp_pre=temp;
206. temp=temp.next;
207. }
208. if(temp_pre==null){
209. head=pnex;
210. pnex.next=temp;
211. }
212. else{
213. temp_pre.next=pnex;
214. pnex.next=temp;
215. }
216. pnex=pnex_nex;
217. }
218. return head;
219. }
220. //判断一个单链表中是否有环,快慢指针
221. public static boolean hasCycle(Node head){
222. boolean flag=false;
223. Node p1=head;
224. Node p2=head;
225. while(p1!=null&&p2!=null){
226. p1=p1.next;
227. p2=p2.next.next;
228. if(p2==p1){
229. flag=true;
230. break;
231. }
232. }
233. return flag;
234. }
235. //判断两个单链表是否相交,如果相交返回第一个节点,否则返回null
236. //如果单纯的判断是否相交,只需要看最后一个指针是否相等
237. public static Node isIntersect(Node head1,Node head2){
238. Node target=null;
239. if(head1==null||head2==null)return target;
240. int len1=getListLength(head1);
241. int len2=getListLength(head2);
242. if(len1>=len2){
243. for(int i=0;i<len1-len2;i++){
244. head1=head1.next;
245. }
246. }else{
247. for(int i=0;i<len2-len1;i++){
248. head2=head2.next;
249. }
250. }
251. while(head1!=null&&head2!=null){
252. if(head1==head2){
253. target=head1;
254. break;
255. }
256. else{
257. head1=head1.next;
258. head2=head2.next;
259. }
260. }
261. return target;
262. }
263. //已知一个单链表中存在环,求进入环中的第一个节点,利用hashmap,不要用ArrayList,因为判断ArrayList是否包含某个元素的效率不高
264. public static Node getFirstNodeInCycleHashMap(Node head){
265. Node target=null;
266. HashMap<Node,Boolean> map=new HashMap<Node,Boolean>();
267. while(head!=null){
268. if(map.containsKey(head))target=head;
269. else{
270. map.put(head, true);
271. }
272. head=head.next;
273. }
274. return target;
275. }
276. //已知一个单链表中存在环,求进入环中的第一个节点,不用hashmap
277. //用快慢指针,与判断一个单链表中是否有环一样,找到快慢指针第一次相交的节点,此时这个节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
278. public static Node getFirstNodeInCycle(Node head){
279. Node fast=head;
280. Node slow=head;
281. while(fast!=null&&fast.next!=null){
282. slow=slow.next;
283. fast=fast.next.next;
284. if(slow==fast)break;
285. }
286. if(fast==null||fast.next==null)return null;//判断是否包含环
287. //相遇节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
288. slow=head;
289. while(slow!=fast){
290. slow=slow.next;
291. fast=fast.next;
292. }//同步走
293. return slow;
294.
295. }
296. //给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete
297. //可惜采用将delete节点value值与它下个节点的值互换的方法,但是如果delete是最后一个节点,则不行,但是总得复杂度还是O(1)
298. public static void deleteNode(Node head,Node delete){
299. //首先处理delete节点为最后一个节点的情况
300. if(delete==null)return;
301. if(delete.next==null){
302. if(head==delete)head=null;
303. else{
304. Node temp=head;
305. while(temp.next!=delete){
306. temp=temp.next;
307. }
308. temp.next=null;
309. }
310. }
311. else{
312. delete.value=delete.next.value;
313. delete.next=delete.next.next;
314. }
315. return;
316. }
317.}
import java.util.HashMap;
import java.util.Scanner;
import java.util.Stack; /**
*
* @author kerryfish
* 关于java中链表的操作
* 1. 求单链表中结点的个数: getListLength
* 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
* 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
* 4. 查找单链表的中间结点: getMiddleNode
* 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
* 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
* 7. 对单链表进行排序,listSort(归并),insertionSortList(插入)
* 8. 判断一个单链表中是否有环: hasCycle
* 9. 判断两个单链表是否相交: isIntersect
* 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap
* 11. 给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete: deleteNode
*/
public class LinkedListSummary {
/**
* @param args
*
*/
public static class Node{
int value;
Node next;
public Node(int n){
this.value=n;
this.next=null;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
Node head=null;
if(in.hasNextInt()){
head=new Node(in.nextInt());
}
Node temp=head;
while(in.hasNextInt()){
temp.next=new Node(in.nextInt());
temp=temp.next;
}
in.close();
//int len=getListLength(head);
//Node reHead=reverseList(head);
//reHead=reverseListRec(reHead);
//Node node_k=reGetKthNode(head,3);
//Node mid=getMiddleNode(head);
//reversePrintListRec(head);
//reversePrintListStack(head);
//Node mergeHead=mergeSortedList(head,null);
//Node sortHead=listSort(head); }
//求单链表中结点的个数: getListLength
public static int getListLength(Node head){
int len=0;
while(head!=null){
len++;
head=head.next;
}
return len;
}
//将单链表反转,循环
public static Node reverseList(Node head){
if(head==null||head.next==null)return head;
Node pre=null;
Node nex=null;
while(head!=null){
nex=head.next;
head.next=pre;
pre=head;
head=nex;
}
return pre;
}
//将单链表反转,递归
public static Node reverseListRec(Node head){
if(head==null||head.next==null)return head;
Node reHead=reverseListRec(head.next);
head.next.next=head;
head.next=null;
return reHead;
}
//查找单链表中的倒数第K个结点(k > 0)
public static Node reGetKthNode(Node head,int k){
if(head==null)return head;
int len=getListLength(head);
if(k>len)return null;
Node target=head;
Node nexk=head;
for(int i=0;i<k;i++){
nexk=nexk.next;
}
while(nexk!=null){
target=target.next;
nexk=nexk.next;
}
return target;
}
//查找单链表的中间结点
public static Node getMiddleNode(Node head){
if(head==null||head.next==null)return head;
Node target=head;
Node temp=head;
while(temp!=null&&temp.next!=null){
target=target.next;
temp=temp.next.next;
}
return target;
}
//从尾到头打印单链表,递归
public static void reversePrintListRec(Node head){
if(head==null)return;
else{
reversePrintListRec(head.next);
System.out.println(head.value);
}
}
//从尾到头打印单链表,栈
public static void reversePrintListStack(Node head){
Stack<Node> s=new Stack<Node>();
while(head!=null){
s.push(head);
head=head.next;
}
while(!s.isEmpty()){
System.out.println(s.pop().value);
}
}
//合并两个有序的单链表head1和head2,循环
public static Node mergeSortedList(Node head1,Node head2){
if(head1==null)return head2;
if(head2==null)return head1;
Node target=null;
if(head1.value>head2.value){
target=head2;
head2=head2.next;
}
else{
target=head1;
head1=head1.next;
}
target.next=null;
Node mergeHead=target;
while(head1!=null && head2!=null){
if(head1.value>head2.value){
target.next=head2;
head2=head2.next;
}
else{
target.next=head1;
head1=head1.next;
}
target=target.next;
target.next=null;
}
if(head1==null)target.next=head2;
else target.next=head1;
return mergeHead;
}
//合并两个有序的单链表head1和head2,递归
public static Node mergeSortedListRec(Node head1,Node head2){
if(head1==null)return head2;
if(head2==null)return head1;
if(head1.value>head2.value){
head2.next=mergeSortedListRec(head2.next,head1);
return head2;
}
else{
head1.next=mergeSortedListRec(head1.next,head2);
return head1;
}
}
//对单链表进行排序,归并排序,在排序里面不建议选用递归的合并有序链表算法,如果链表长度较长,很容易出现栈溢出
public static Node listSort(Node head){
Node nex=null;
if(head==null||head.next==null)return head;
else if(head.next.next==null){
nex=head.next;
head.next=null;
}
else{
Node mid=getMiddleNode(head);
nex=mid.next;
mid.next=null;
}
return mergeSortedList(listSort(head),listSort(nex));//合并两个有序链表,不建议递归
}
//对单链表进行排序,插入排序
public Node insertionSortList(Node head) {
if(head==null||head.next==null)return head;
Node pnex=head.next;
Node pnex_nex=null;
head.next=null;
while(pnex!=null){
pnex_nex=pnex.next;
Node temp=head;
Node temp_pre=null;
while(temp!=null){
if(temp.value>pnex.value)break;
temp_pre=temp;
temp=temp.next;
}
if(temp_pre==null){
head=pnex;
pnex.next=temp;
}
else{
temp_pre.next=pnex;
pnex.next=temp;
}
pnex=pnex_nex;
}
return head;
}
//判断一个单链表中是否有环,快慢指针
public static boolean hasCycle(Node head){
boolean flag=false;
Node p1=head;
Node p2=head;
while(p1!=null&&p2!=null){
p1=p1.next;
p2=p2.next.next;
if(p2==p1){
flag=true;
break;
}
}
return flag;
}
//判断两个单链表是否相交,如果相交返回第一个节点,否则返回null
//如果单纯的判断是否相交,只需要看最后一个指针是否相等
public static Node isIntersect(Node head1,Node head2){
Node target=null;
if(head1==null||head2==null)return target;
int len1=getListLength(head1);
int len2=getListLength(head2);
if(len1>=len2){
for(int i=0;i<len1-len2;i++){
head1=head1.next;
}
}else{
for(int i=0;i<len2-len1;i++){
head2=head2.next;
}
}
while(head1!=null&&head2!=null){
if(head1==head2){
target=head1;
break;
}
else{
head1=head1.next;
head2=head2.next;
}
}
return target;
}
//已知一个单链表中存在环,求进入环中的第一个节点,利用hashmap,不要用ArrayList,因为判断ArrayList是否包含某个元素的效率不高
public static Node getFirstNodeInCycleHashMap(Node head){
Node target=null;
HashMap<Node,Boolean> map=new HashMap<Node,Boolean>();
while(head!=null){
if(map.containsKey(head))target=head;
else{
map.put(head, true);
}
head=head.next;
}
return target;
}
//已知一个单链表中存在环,求进入环中的第一个节点,不用hashmap
//用快慢指针,与判断一个单链表中是否有环一样,找到快慢指针第一次相交的节点,此时这个节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
public static Node getFirstNodeInCycle(Node head){
Node fast=head;
Node slow=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast)break;
}
if(fast==null||fast.next==null)return null;//判断是否包含环
//相遇节点距离环开始节点的长度和链表投距离环开始的节点的长度相等
slow=head;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}//同步走
return slow; }
//给出一单链表头指针head和一节点指针delete,O(1)时间复杂度删除节点delete
//可惜采用将delete节点value值与它下个节点的值互换的方法,但是如果delete是最后一个节点,则不行,但是总得复杂度还是O(1)
public static void deleteNode(Node head,Node delete){
//首先处理delete节点为最后一个节点的情况
if(delete==null)return;
if(delete.next==null){
if(head==delete)head=null;
else{
Node temp=head;
while(temp.next!=delete){
temp=temp.next;
}
temp.next=null;
}
}
else{
delete.value=delete.next.value;
delete.next=delete.next.next;
}
return;
}
}

学习记录 java 链表知识的更多相关文章

  1. 学习记录-java基础部分(一)

    学习记录-java基础部分(一) 参考:GitHub上的知名项目:javaGuide : https://github.com/Snailclimb/JavaGuide/blob/master/doc ...

  2. 学习记录 java 值类型和引用类型的知识

    1. Java中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值, 那么调用这个方法是传入的变量的值也将改变 ...

  3. python核心编程学习记录之基础知识

    虽然对python的基础知识有所了解,但是为了更深入的学习,要对python的各种经典书籍进行学习 第一章介绍python的优缺点,略过 第二章介绍python起步,第三章介绍python基础,仅记录 ...

  4. JVM学习记录-Java内存模型(二)

    对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用vo ...

  5. Python学习记录1-基础知识

    基础知识 基础 #简单记录了部分基础知识 #普通的打印字符串 >>> print("hello world") hello world ------------- ...

  6. 学习记录 java session保存用户登录

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  7. 学习记录 java 哈希

    哈希表(Hash Table,又叫散列表),是存储键值对(Key-value)的表,之所以不叫它Map(键值对一起存储一般叫做Map),是因为它下面的特性:它能把关键码(key)映射到表中的一个位置来 ...

  8. 学习记录 java泛型资料

    java泛型资料: 1. 概述在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型.例如原先的类型List,现在在细分成Lis ...

  9. 学习记录 java随机数的产生机制

    java 随机数 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100 ...

随机推荐

  1. CSS常用样式整理

    元素边框显示圆角:-moz-border-radius适用于火狐浏览器,-webkit-border-radius适用于Safari和Chrome两种浏览器. 浏览器渐变背景颜色: FILTER: p ...

  2. SecureCRT自动记录日志【记录键入的所有命令和打印的结果信息】

  3. DBA_Oracle海量数据处理分析(方法论)

    2014-12-18 Created By BaoXinjian

  4. ImageLoader_ _Universal-Image-Loader完全解析(一)之介绍与使用详解

    转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50439814 本文出自:[江清清的博客] (一).前言: 已经半个月 ...

  5. rsyncd.conf 文件

    uid = nobodygid = nobodymax connections = 10timeout = 60use chroot = noread only = falsepid file=/va ...

  6. 一些BOOTSTRAP的问题

    老师好,有几个点不是很明白,劳烦老师帮忙解惑 <1>不是特别清楚nav和navbar的区别,视频中用的是nav标签,而class则标明navbar,是不是这里的nav其实没有什么作用,而c ...

  7. lower_bound 和 upper_bound

    Return iterator to lower bound Returns an iterator pointing to the first element in the range [first ...

  8. nyoj 68 三点顺序

    点击打开链接 三点顺序 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 现在给你不共线的三个点A,B,C的坐标,它们一定能组成一个三角形,现在让你判断A,B,C是顺时针给 ...

  9. WayPoint寻路

    寻路在游戏开发中的重要性,不用多说了.从大型ARPG游戏到小规模体验游戏,都会不同程度的用到寻路功能. 塔防类游戏,战棋类游戏经常用到waypoint(路径)寻路. 下面我们来介绍一下waypoint ...

  10. 蓝桥杯---汉字取首字母(位运算 & 水题)

    确实题目虽然有点水,但是开始的时候好像还真的没有想到怎么提取出这个编号一不小心感觉可以可以用unsigned char 这种类型,直接转为16进制,但是之后发现虽然第一次在codeblock中还行,但 ...