转载请注明本文出处:http://www.cnblogs.com/Starshot/p/6918569.html

链表的结构是由一个一个节点组成的,所谓链,就是每个节点的头尾连在一起。而单向链表就是:每个节点包含了当前节点的值和下一个节点引用。双向链表就是每个节点包含了当前节点的值和上下两个节点的引用。相对于数组结构,链表的增删效率会更加高。

这边文章主要讲怎么用Java实现一个简单的链表结构:单向无环链表。以及实现一些数据处理的方法。

首先,新建一个节点类(本次例子中的节点值都是字符串类型):

  1. public class Node {
  2.  
  3. private String value;
  4. private Node next;
  5.  
  6. public Node(String value){
  7. this.value=value;
  8. }
  9. public Node(){
  10.  
  11. }
  12.  
  13. public String getValue(){
  14. return value;
  15. }
  16.  
  17. public Node getnext(){
  18. return next;
  19. }
  20.  
  21. public void setValue(String value){
  22. this.value=value;
  23. }
  24.  
  25. public void setNext(Node next){
  26. this.next=next;
  27. }
  28. }

然后再建一个链表类:

  1. public class MyLinkedTable {
  2.  
  3. Node head=new Node();
  4.  
  5. //向链表中增加值
  6. public boolean add(String str){
  7. Node node=new Node(str);
  8. if(head.getnext()==null){
  9. head.setNext(node);;
  10. return true;
  11. }
  12.  
  13. Node tmp=head;
  14.  
  15. while(tmp.getnext()!=null){
  16. tmp=tmp.getnext();
  17. }
  18.  
  19. tmp.setNext(node);
  20.  
  21. return true;
  22.  
  23. }
  24. //已知某个节点,然后删除该节点
  25. public boolean delete(Node node){
  26. Node next=node.getnext();
  27. Node nextAddress=next.getnext();
  28. String nextValue=next.getValue();
  29. node.setNext(nextAddress);
  30. node.setValue(nextValue);
  31. return true;
  32. }
  33.  
  34. //删除第index个节点,index从1开始
  35. public boolean delete(int index){
  36.  
  37. if(index>length()||index<1){
  38. return false;
  39. }
  40.  
  41. int i=1;
  42. Node temp=head.getnext();
  43. while(i<index){
  44. temp=temp.getnext();
  45. i++;
  46. }
  47.  
  48. Node next=temp.getnext();
  49. Node nextAddress=next.getnext();
  50. String nextValue=next.getValue();
  51. temp.setNext(nextAddress);
  52. temp.setValue(nextValue);
  53.  
  54. return true;
  55. }
  56.  
  57. //获得第index个节点的值
  58. public String get(int index){
  59. if(index>length()||index<1){
  60. return null;
  61. }
  62.  
  63. int i=1;
  64. Node temp=head.getnext();
  65. while(i<index){
  66. temp=temp.getnext();
  67. i++;
  68. }
  69.  
  70. return temp.getValue();
  71. }
  72.  
  73. //获取链表里面数据的长度,也就是插入了多少个值。
  74. public int length(){
  75.  
  76. if(head.getnext()==null){
  77. return 0;
  78. }
  79.  
  80. int i=1;
  81. Node temp=head.getnext();
  82. while((temp=temp.getnext())!=null){
  83. i++;
  84. }
  85.  
  86. return i;
  87. }
  88.  
  89. //反转链表
  90. public void reverseTable(){
  91. Node node1=head.getnext();
  92.  
  93. if(node1==null){
  94. return;
  95. }
  96.  
  97. Node preNode=null;
  98. Node curNode=node1;
  99.  
  100. while(true){
  101. Node origNextNode=curNode.getnext();
  102. curNode.setNext(preNode);
  103. if(origNextNode==null){
  104. head.setNext(curNode);
  105. break;
  106. }
  107. preNode=curNode;
  108. curNode=origNextNode;
  109. }
  110.  
  111. }
  112.  
  113. //获取中间链表
  114. public String getMid(){
  115.  
  116. Node slowPointer=this.head.getnext(),fastPointer=this.head.getnext();
  117. while(fastPointer!=null&&fastPointer.getnext()!=null&&fastPointer.getnext().getnext()!=null){
  118. slowPointer=slowPointer.getnext();
  119. fastPointer=fastPointer.getnext().getnext();
  120. }
  121.  
  122. return slowPointer.getValue();
  123.  
  124. }
  125.  
  126. //删除重复链表
  127. public void deleteDuplicateNode(){
  128. Node nodeCur=head.getnext();
  129.  
  130. if(nodeCur==null) return;
  131.  
  132. while(nodeCur.getnext()!=null){
  133. Node lastNode=nodeCur;
  134. Node compareNode=lastNode.getnext();
  135. while(compareNode!=null){
  136.  
  137. if(nodeCur.getValue().equals(compareNode.getValue())){
  138. lastNode.setNext(compareNode.getnext());
  139. compareNode=compareNode.getnext();
  140. }else{
  141.  
  142. lastNode=compareNode;
  143. compareNode=compareNode.getnext();
  144. }
  145. }
  146. nodeCur=nodeCur.getnext();
  147. }
  148. }
  149. }

需要说明一下,这个链表结构是以head为起始节点,head指向插入的第一个节点(反转后就是最后一个),head本身的value一直都是空的,它只作为起始节点入口存在,不参与节点的计数,所以链表的节点总数(插入数据总数)是不包括head在内的。

接下来对某些方法进行说明:

1.链表反转

  1. //链表翻转就是把原来的1>2>3>4变成4>3>2>1,所以原来在最前面的节点要变成在最后面,最后面的要变成最前面
  2. //就是head的地址引用要变成最后一个节点的,原来head后的第一个节点的地址引用要由第二的节点变为NULL,原来第二个节点的地址引用要由第三个节点变成第一个节点
  3. //以此类推,一直翻转到最后一个。然后把head的地址引用变成最后一个。
  4. //在这个链表里面,head的位置是一直不变的,它永远是最前面,在head之后的节点才开始翻转。
  5. public void reverseTable(){
  6. Node node1=head.getnext();
  7.  
  8. if(node1==null){
  9. return;
  10. }
  11.  
  12. Node preNode=null;
  13. Node curNode=node1;
  14.  
  15. while(true){
  16. Node origNextNode=curNode.getnext();
  17. curNode.setNext(preNode);
  18. if(origNextNode==null){
  19. head.setNext(curNode);
  20. break;
  21. }
  22. preNode=curNode;
  23. curNode=origNextNode;
  24. }
  25.  
  26. }

2.获得中间节点:

  1. //通过用快慢指针来找到中间节点,快指针的速度为慢指针的两倍,慢指针一次走一个节点,快指针一次走两个节点,
  2. //当快指针走到尽头时,慢指针刚好为中间值,当快指针走到倒数第二个节点时,慢指针为上中位数。
  3. //fastPointer!=null用来判断链表表内除head外有没有其它节点,fastPointer.getnext()!=null判断是否为最后一个节点,
  4. //fastPointer.getnext().getnext()!=null判断是否为倒数第二个节点。
  5. public String getMid(){
  6.  
  7. Node slowPointer=this.head.getnext(),fastPointer=this.head.getnext();
  8. while(fastPointer!=null&&fastPointer.getnext()!=null&&fastPointer.getnext().getnext()!=null){
  9. slowPointer=slowPointer.getnext();
  10. fastPointer=fastPointer.getnext().getnext();
  11. }
  12.  
  13. return slowPointer.getValue();
  14.  
  15. }

3.删除具有相同值的节点(重复节点):

  1. //删除具有相同值的节点
  2. //基本原理是用第一个节点的值和第二个节点值比较,然后和第三个节点比较,以此类推。此时第一个节点为当前节点nodeCur,第二第三以及之后的节点为比较节点compareNode
  3. //一轮比较完毕后,第二个节点就变成nodeCur,之后那些节点就是compareNode
  4. //如果遇到有相同的值的节点,就将该节点的上个节点的next值为该节点的下个节点:lastNode.setNext(compareNode.getnext()),此时该节点就在链表里失去引用了,就相当于删除了。
  5. //所以需要lastNode引用来保存当前比较节点的上一个节点
  6. public void deleteDuplicateNode(){
  7. Node nodeCur=head.getnext();
  8.  
  9. if(nodeCur==null) return;
  10.  
  11. while(nodeCur.getnext()!=null){
  12. Node lastNode=nodeCur;
  13. Node compareNode=lastNode.getnext();
  14. while(compareNode!=null){
  15.  
  16. if(nodeCur.getValue().equals(compareNode.getValue())){
  17. lastNode.setNext(compareNode.getnext());
  18. compareNode=compareNode.getnext();
  19. }else{
  20.  
  21. lastNode=compareNode;
  22. compareNode=compareNode.getnext();
  23. }
  24. }
  25. nodeCur=nodeCur.getnext();
  26. }
  27. }

写好之后可以测试一下:

  1. public class Test {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. MyLinkedTable m=new MyLinkedTable();
  6. m.add("1");
  7. m.add("2");
  8. m.add("3");
  9. m.add("4");
  10. m.add("5");
  11. m.add("6");
  12.  
  13. for(int i=1;i<=m.length();i++){
  14. System.out.println(i+":"+m.get(i));
  15. }
  16. System.out.println("length:"+m.length());
  17.  
  18. m.reverseTable();
  19. for(int i=1;i<=m.length();i++){
  20. System.out.println(i+":"+m.get(i));
  21. }
  22. System.out.println("length:"+m.length());
  23.  
  24. m.delete(2);
  25. for(int i=1;i<=m.length();i++){
  26. System.out.println(i+":"+m.get(i));
  27. }
  28. System.out.println("length:"+m.length());
  29.  
  30. System.out.println(m.getMid());
  31.  
  32. }
  33.  
  34. }

运行输出如下:

1:1
2:2
3:3
4:4
5:5
6:6
length:6
1:6
2:5
3:4
4:3
5:2
6:1
length:6
1:6
2:4
3:3
4:2
5:1
length:5
3

还有测试删除重复节点的:

  1. public class Test2 {
  2.  
  3. public static void main(String[] args) {
  4. MyLinkedTable m=new MyLinkedTable();
  5. m.add("1");
  6. m.add("2");
  7. m.add("3");
  8. m.add("2");
  9. m.add("2");
  10. m.add("6");
  11.  
  12. for(int i=1;i<=m.length();i++){
  13. System.out.println(i+":"+m.get(i));
  14. }
  15. System.out.println("length:"+m.length());
  16.  
  17. m.deleteDuplicateNode();
  18.  
  19. for(int i=1;i<=m.length();i++){
  20. System.out.println(i+":"+m.get(i));
  21. }
  22. System.out.println("length:"+m.length());
  23. }
  24.  
  25. }

运行输出:

1:1
2:2
3:3
4:2
5:2
6:6
length:6
1:1
2:2
3:3
4:6
length:4

以上就是用java实现单向无环链表的详细过程和解释,如果不妥之处,欢迎指出。

(原创)用Java实现链表结构对象:单向无环链表的更多相关文章

  1. JavaScript实现单向链表结构

    参考资料 一.什么是链表结构? 1.1.简介 链表和数组一样, 可以用于存储一系列的元素, 但是链表和数组的实现机制完全不同,链表中的元素在内存不是连续的空间,链表的每个元素由一个存储元素本身(数据) ...

  2. 【二叉树->链表】二叉树结构转双向线性链表结构(先序遍历)

    二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解.然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样.下面以先序为例. 方法一: 递归法.递归遍历二叉树,因为 ...

  3. Linux内核--链表结构(一)

    一.前言 Linux内核链表结构是一种双向循环链表结构,与传统的链表结构不同,Linux内核链表结构仅包含前驱和后继指针,不包含数据域.使用链表结构,仅需在结构体成员中包含list_head*成员就行 ...

  4. 《Java数据结构》链表结构(单向链表,双向链表)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指 ...

  5. JAVA基础——链表结构之单链表

    链表:一种数据存储结构.学链表首先要搞懂数组,按朋友的话说,数组和链表的关系就相当于QQ2008和QQ2009. 除非要通过索引频繁访问各个数据,不然大多数情况下都可以用链表代替数组. 链表部分主要要 ...

  6. Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换

    Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换 { "@type":"java.lang.Runti ...

  7. 由PHP实现单向链表引发的对象赋值,对象传参,链表操作引发的一系列问题

    2019年2月25日14:21:13 测试版本php 5.4 ,5.6,7.0,7.2 代码请看: https://www.cnblogs.com/zx-admin/p/10373866.html 1 ...

  8. 面试题:JVM在Java堆中对对象的创建、内存结构、访问方式

    一.对象创建过程 1.检查类是否已被加载 JVM遇到new指令时,首先会去检查这个指令参数能否在常量池中定位到这个类的符号引用,检查这个符号引用代表的类是否已被加载.解析.初始化,若没有,则进行类加载 ...

  9. java实现链表结构详细代码

    一.数据准备 1. 定义节点 2.   定义链表 1.数据部分 2.节点部分 class DATA //数据节点类型 { String key; String name; int age; } cla ...

随机推荐

  1. xshell配色Solarized Dark

    转自:xshell配色Solarized Dark [Solarized_Dark] text(bold)= magenta(bold)=6c71c4 text= white(bold)=fdf6e3 ...

  2. 谈谈一些有趣的CSS题目(十五)-- 谈谈 CSS 关键字 initial、inherit 和 unset

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. STM32、Cortex-A、Cortex-R、Cortex-M、SecurCore

    STM32是就是基于Cortex-M3这个核生产的CPU. arm7是arm公司推出的以V4指令集设计出来的arm核--其代表的芯片有s3c44b0 arm9是arm公司推出的以V5指令集设计出来的a ...

  4. 保证Android后台不被杀死的几种方法

    由于各种原因,在开发Android应用时会提出保证自己有一个后台一直运行的需求,如何保证后台始终运行,不被系统因为内存低杀死,不被任务管理器杀死,不被软件管家等软件杀死等等还是一个比较困难的问题.网上 ...

  5. HTTP长连接、短连接使用及测试

    概念 HTTP短连接(非持久连接)是指,客户端和服务端进行一次HTTP请求/响应之后,就关闭连接.所以,下一次的HTTP请求/响应操作就需要重新建立连接. HTTP长连接(持久连接)是指,客户端和服务 ...

  6. Native App和Web App 的差异

    开发者们都知道在高端智能手机系统中有两种应用程序:一种是基于本地(操作系统)运行的APP:一种是基于高端机的浏览器运行的WebApp,本文将主要讲解后者. WebApp与Native App有何区别呢 ...

  7. Angularjs快速入门(二)

    说说上一节的例子,$scope 我们没有创建这个对象,直接绑定就能获取里面的对象,这种风格遵循了一种叫迪米特法则的设计模式. 然后angular还有一种很强大的功能叫“指令”. 就是你可以吧模板编写成 ...

  8. Excel基本操作1

    Excel的基本操作之二,录入及快速填充.不足之处,欢迎补充

  9. C语言精要总结-指针系列(一)

    考虑到指针内容繁多,这里将指针作为一个系列,从简入繁,一点一点深挖并掌握这C语言的精华.初步计划如下 此文为指针系列第一篇: C语言精要总结-指针系列(一) 内存与地址 我们可以把内存看做一排连续的房 ...

  10. base 镜像 - 每天5分钟玩转容器技术(10)

    上一节我们介绍了最小的 Docker 镜像,本节讨论 base 镜像. base 镜像有两层含义: 不依赖其他镜像,从 scratch 构建. 其他镜像可以之为基础进行扩展. 所以,能称作 base ...