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. Linux常用命令记录

    产用Linux命令 cat /proc/partitions //查看系统分区情况 fdisk -l /dev/sdb //查看磁盘物理存储 mount /dev/目录 /mnt/目录 //挂载文件 ...

  2. hibernate级联与反向

    cascade:设置本表与关联表之间的级联操作,如:设置为save-update,则插入或更新对象时同时保存或更新另一端的表,但不会产生关联关系数据,除非inverse为false. inverse: ...

  3. Form_Form Builder开发基于视图页面和自动代码生成包(案例)

     2014-01-06 Created By BaoXinjian

  4. Windows服务程序和安装程序制作

    转:http://www.cr173.com/html/15350_1.html 本文介绍了如何用C#创建.安装.启动.监控.卸载简单的Windows Service 的内容步骤和注意事项. 一.创建 ...

  5. 从千分位格式化谈JS性能优化

    所谓的千分位形式,即从个位数起,每三位之间加一个逗号.例如“10,000”.针对这个需求,我起初写了这样一个函数: // 方法一function toThousands(num) {var resul ...

  6. 转_Java中常用的设计模式总结

    1.工厂模式:客户类和工厂类分开.消费者任何时候需要某种产品,只需向工厂请求即可.消费者无须修改就可以接纳新产品.缺点是当产品修改时,工厂类也要做相应的修改.如:如何创建及如何向客户端提供. 2.建造 ...

  7. db2常用名词

    数据库---表空间----表-----段-------分区 数据库实例:就是server 数据库模式:就是逻辑上的用户

  8. linux命令行下导出导入.sql文件

    一.导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径):1.导出数据和表结构(以管理员身份运行): ------------------------------------ ...

  9. 拥抱高效、拥抱 Bugtags 之来自用户的声音

    小编按:这是一篇 Bugtags 用户来稿,主要是介绍了 Bugtags 使用的方法及其带来的效率的提升,谢谢介博同学对 Bugtags 的信赖和支持.小编在这里诚邀各位热心用户向我们投稿,说出你使用 ...

  10. Mingyang.net:用注解校验数据

    注解校验依赖的是javax.validation和hibernate-validaton. <dependency> <groupId>javax.validation< ...