单链表实现及其基本操作

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

单链表实现及其基本操作的相关文章

递归实现单链表的各种基本操作

1 #include<iostream> 2 using namespace std; 3 4 #define OK 1 5 #define ERROR 0 6 typedef int Status; 7 8 typedef struct LNode 9 { 10 int data; //结点的数据域 11 struct LNode *next; //结点的指针域 12 }LNode, *LinkList; //LinkList为指向结构体LNode的指针类型 13 14 void creat

数据结构----顺序表与单链表(JAVA)

下面为学习顺序表和单链表的一些基本操作函数: 1 public class SeqList<T> extends Object { 2 protected int n; 3 protected Object[] element; 4 5 public SeqList(int length) { 6 this.element = new Object[length]; 7 this.n = 0; 8 } 9 10 public SeqList() { 11 this(64); 12 } 13 1

数据结构笔记5带头结点单链表

/* 本次操作是对带头节点单链表的操作  包括删除  插入 判空 建立  包括删除插入函数  显示函数 目的是为了对单链表做一个基本操作的总结----1*/ #include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFLAG 0typedef struct LNode{ int data; struct LNo

小猪的数据结构辅助教程——2.2 线性表中的单链表

小猪的数据结构辅助教程--2.2 线性表中的单链表 标签(空格分隔): 数据结构 本节学习路线图与学习要点 学习要点: 1.理解顺序表以及单链表各自的有点以及缺点! 2.熟悉单链表的形式,对于头指针,头结点,尾结点,数据域和指针域这些名词要知道是什么! 3.熟悉单链表的结点结构 4.区分头指针与头结点! 5.熟悉创建单链表的两种方式:头插法和尾插法 6.了解单链表12个基本操作的逻辑 7.有趣的算法题:查找单链表的中间结点~ 1.单链表的引入(顺序表与单链表的PK) 2.单链表的结构图以及一些名

数据结构复习--java实现单链表基本操作

单链表的基本操作包括建立单链表.查找运算(按序查找和按值查找).插入运算(前插和后插)和删除运算.下面给出具体的java实现程序: package com.zpp.test; //首先创建一个节点类 public class Node { private Node next; //指针域 private int data;//数据域 public Node( int data) { this. data = data; } } package com.zpp.test; public class

单链表的实现及其基本操作

结点的引入 链表是一种链式存储结构,链式存储结构的特点是用一组任意的存储单元存储数据元素.为了能正确表示数据元素之间的线性关系,需引入结点概念.一个结点表示链表中的一个数据元素,节点中除了储存数据元素的信息, 还必须存放指向下一个节点的的指针(单.双链表的最后一个节点除外,它们存储的是一个空指针NULL) 结点的结构如下图所示: 代码如下: 1 typedef struct node{ 2 int data; 3 struct node* pNext; 4 }Node, *PNode; 注:这里

《实验课---单链表的基本操作》

//线性表---链表的基本操作#include<stdio.h>#include<stdlib.h>#include<conio.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define NULL 0typedef int Status; //函数结果状态代码typedef int ElemType; //数据元素类型//------线性表的单链表存储结构

数据结构实验报告-实验一 顺序表、单链表基本操作的实现

实验一    顺序表.单链表基本操作的实现   l  实验目的 1.顺序表 (1)掌握线性表的基本运算. (2)掌握顺序存储的概念,学会对顺序存储数据结构进行操作. (3)加深对顺序存储数据结构的理解,逐步培养解决实际问题的编程能力. l  实验内容 1. 顺序表 1.编写线性表基本操作函数: (1)InitList(LIST *L,int ms)初始化线性表: (2)InsertList(LIST *L,int item,int rc)向线性表的指定位置插入元素: (3)DeleteList1

C语言实现单链表(带头结点)的基本操作

我在之前一篇博客<C语言实现单链表(不带头结点)的基本操作>中具体实现了不带头结点的单链表的11种操作:如计算链表长度.初始化.创建链表.清空链表等等.但是在实际使用中,带头结点的单链表往往比不带头结点的单链表用的更多,使用也更为方便.因为不用单独考虑第一个节点的情况了,第一个节点和其他后续节点的处理全都一样了,简化操作.这篇博客将会来实现带头结点的单链表的11种操作.代码上传至: https://github.com/chenyufeng1991/LinkedList_HeadNode  .