主要分析示例:

一、循环链表简述

二、单链表循环链表

三、双链表循环链表

一、循环链表简述

循环链表即链表形成了一个循环的结构,尾节点不再指向NULL,而是指向头节点HEAD,此时判定链表的结束是尾节点是否指向了头节点HEAD。基本结构为:

备注:其中单链表节点和双链表节点类和接口ICommOperate<T>与上篇一致,这里不在赘述。参考:JAVA链表操作:单链表和双链表http://www.cnblogs.com/xiaoxing/p/5969133.html

二、单链表循环链表

  1. package LinkListTest;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class SingleCycleLinkList implements ICommOperate<SNode> {
  5. private SNode head = new SNode("HEAD") ; // 公共头指针,声明之后不变
  6. private int size = 0 ;
  7. public int getSize() {
  8. return this.size;
  9. }
  10.  
  11. /*
  12. * 链表插入,每次往末端插入,判定末端的标准为next是否指向head
  13. * */
  14. @Override
  15. public boolean insertNode(SNode node) {
  16. boolean flag = false ;
  17.  
  18. initLinkList() ; // 初始化链表
  19. if( this.size==0 ){ // 空链表
  20. this.head.setNextNode(node) ;
  21. node.setNextNode(this.head) ;
  22. }else{
  23. SNode current = this.head ;
  24. while( current.getNextNode()!=this.head ){ // 找到末端节点
  25. current = current.getNextNode() ;
  26. }
  27. current.setNextNode(node) ;
  28. node.setNextNode(this.head) ; // 循坏链表,尾节点指向head
  29. }
  30. this.size++ ;
  31. flag = true ;
  32.  
  33. return flag;
  34. }
  35.  
  36. /*
  37. * 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
  38. * */
  39. @Override
  40. public boolean insertPosNode(int pos, SNode node) {
  41. boolean flag = true ;
  42. SNode current = this.head.getNextNode() ;
  43.  
  44. initLinkList() ;// 初始化链表
  45. if( this.size==0 ){ // 链表为空
  46. this.head.setNextNode(node) ;
  47. node.setNextNode(this.head) ;// 循坏链表,尾节点指向head
  48. this.size++ ;
  49. }else if( this.size<pos ){ // pos位置大于链表长度,插入末端
  50. insertNode(node) ;
  51. }else if( pos>0 && pos<=this.size ){ // 链表内节点
  52. // 1、找到要插入pos位置节点和前节点,node将插入两个节点之间
  53. int find = 0;
  54. SNode preNode = this.head; // 前节点
  55. SNode currentNode = current; // 当前节点
  56. while( find<pos-1 && currentNode!=this.head ){
  57. preNode = current ; // 前节点后移
  58. currentNode = currentNode.getNextNode() ; // 当前节点后移
  59. find++ ;
  60. if( find<pos-1 && currentNode!=this.head ){ // 未结束寻找节点前,后移前节点
  61. current = current.getNextNode() ;
  62. }
  63. }
  64. // System.out.println(preNode);
  65. // System.out.println(currentNode);
  66.  
  67. // 2、插入节点
  68. preNode.setNextNode(node);
  69. node.setNextNode(currentNode);
  70. this.size++ ;
  71. }else {
  72. System.out.println("位置信息错误");
  73. flag = false ;
  74. }
  75.  
  76. return flag;
  77. }
  78.  
  79. private void initLinkList(){
  80. if( size==0 ){
  81. this.head.setNextNode(this.head);
  82. }
  83. }
  84.  
  85. /*
  86. * 指定链表的节点pos,删除对应节点。方式:找到要删除节点的前后节点,进行删除,下标从1开始
  87. * */
  88. @Override
  89. public boolean deleteNode(int pos) {
  90. boolean flag = false;
  91. SNode current = this.head.getNextNode() ;
  92. if( pos<=0 || pos>this.size || current==this.head ){
  93. System.out.println("位置信息错误或链表无信息");
  94. }else{
  95. // 1、找到要删除节点的前后节点
  96. int find = 0;
  97. SNode preNode = this.head; // 前节点
  98. SNode nextNode = current.getNextNode(); // 后节点
  99. while( find<pos-1 && nextNode!=this.head ){
  100. preNode = current ; // 前节点后移
  101. nextNode = nextNode.getNextNode() ; // 后节点后移
  102. find++ ;
  103. if( find<pos-1 && nextNode!=this.head ){ // 未结束找节点前,后移"前节点"
  104. current = current.getNextNode() ;
  105. }
  106. }
  107. // System.out.println(preNode);
  108. // System.out.println(nextNode);
  109.  
  110. // 2、删除节点
  111. preNode.setNextNode(nextNode);
  112. System.gc(); // 回收删除节点
  113. this.size-- ;
  114. flag = true ;
  115. }
  116.  
  117. return flag;
  118. }
  119.  
  120. /*
  121. * 指定链表的节点pos,修改对应节点,下标从1开始
  122. * */
  123. @Override
  124. public boolean updateNode(int pos, Map<String, Object> map) {
  125. boolean flag = false ;
  126. SNode node = getNode(pos, map); // 获得相应位置pos的节点
  127. if( node!=null ){
  128. String data = (String) map.get("data") ;
  129. node.setData(data);
  130. flag = true ;
  131. }
  132. return flag;
  133. }
  134.  
  135. /*
  136. * 找到指定链表的节点pos,下标从1开始
  137. * */
  138. @Override
  139. public SNode getNode(int pos, Map<String, Object> map) {
  140. SNode current = this.head.getNextNode() ;
  141. if( pos<=0 || pos>this.size || current==this.head ){
  142. System.out.println("位置信息错误或链表不存在");
  143. return null;
  144. }
  145. int find = 0 ;
  146. while( find<pos-1 && current!=this.head ){
  147. current = current.getNextNode() ;
  148. find++ ;
  149. }
  150. return current;
  151. }
  152.  
  153. /*
  154. * 打印链表
  155. * */
  156. @Override
  157. public void printLink() {
  158. int length = this.size ;
  159. if( length==0 ){
  160. System.out.println("链表为空!");
  161. return ;
  162. }
  163. SNode current = this.head.getNextNode() ;
  164. System.out.println("总共有节点数: " + length +" 个");
  165. int find = 0 ;
  166. while( current!=this.head ){
  167. System.out.println("第 " + (++find) + " 个节点 :" + current);
  168. current=current.getNextNode() ;
  169. }
  170. }
  171.  
  172. public static void main(String[] args) {
  173. SingleCycleLinkList scll = new SingleCycleLinkList() ;
  174. SNode node1 = new SNode("节点1");
  175. SNode node2 = new SNode("节点2");
  176. SNode node3 = new SNode("节点3");
  177. SNode node4 = new SNode("节点4");
  178. SNode node5 = new SNode("节点5");
  179. SNode node6 = new SNode("插入指定位置");
  180. // scll.insertPosNode(scll.getSize()+1, node1) ;
  181. // scll.insertPosNode(scll.getSize()+1, node2) ;
  182. // scll.insertPosNode(scll.getSize()+1, node3) ;
  183. // scll.insertPosNode(scll.getSize()+1, node4) ;
  184. // scll.insertPosNode(scll.getSize()+1, node5) ;
  185. scll.insertNode(node1);
  186. scll.insertNode(node2);
  187. scll.insertNode(node3);
  188. scll.insertNode(node4);
  189. scll.insertNode(node5);
  190.  
  191. System.out.println("*******************输出链表*******************");
  192. scll.printLink();
  193.  
  194. System.out.println("*******************获得指定链表节点*******************");
  195. int pos = 2 ;
  196. System.out.println("获取链表第 "+pos+" 个位置数据 :"+scll.getNode(pos, null));
  197.  
  198. System.out.println("*******************向链表指定位置插入节点*******************");
  199. int pos1 = 3 ;
  200. System.out.println("将数据插入第"+pos1+"个节点:");
  201. scll.insertPosNode(pos1, node6) ;
  202. scll.printLink();
  203.  
  204. System.out.println("*******************删除链表指定位置节点*******************");
  205. int pos2 = 3 ;
  206. System.out.println("删除第"+pos2+"个节点:");
  207. scll.deleteNode(pos2) ;
  208. scll.printLink();
  209.  
  210. System.out.println("*******************修改链表指定位置节点*******************");
  211. int pos3 = 3 ;
  212. System.out.println("修改第"+pos3+"个节点:");
  213. Map<String, Object> map = new HashMap<>() ;
  214. map.put("data", "this is a test") ;
  215. scll.updateNode(pos3, map) ;
  216. scll.printLink();
  217. }
  218.  
  219. }

、双链表循环链表

  1. package LinkListTest;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. public class DoubleCycleLinkList implements ICommOperate<DNode>{
  7. private DNode head = new DNode("HEAD"); // 公共头指针,声明之后不变
  8. private int size = 0 ; // 记录链表节点数量
  9.  
  10. public int getSize() {
  11. return this.size;
  12. }
  13.  
  14. /*
  15. * 链表插入,每次往末端插入,判定末端的标准为next是否指向head
  16. * */
  17. @Override
  18. public boolean insertNode(DNode node) {
  19. boolean flag = false ;
  20.  
  21. initLinkList() ; // 初始化链表
  22. DNode current = this.head ;
  23. if( this.size==0 ){ // 空链表
  24. this.head.setNextNode(node) ;
  25. node.setPriorNode(this.head);
  26. node.setNextNode(this.head) ;
  27. }else{ // 链表内节点
  28. while( current.getNextNode()!=this.head ){ // 找到末端节点
  29. current = current.getNextNode() ;
  30. }
  31. current.setNextNode(node) ;
  32. node.setPriorNode(current);
  33. node.setNextNode(this.head) ; // 循坏链表,尾节点指向head
  34. }
  35. this.size++ ;
  36. flag = true ;
  37.  
  38. return flag;
  39. }
  40.  
  41. /*
  42. * 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
  43. * */
  44. @Override
  45. public boolean insertPosNode(int pos, DNode node) {
  46. boolean flag = true;
  47.  
  48. initLinkList() ; // 初始化链表
  49. DNode current = this.head.getNextNode() ;
  50. if( this.size==0 ){ // 链表为空
  51. this.head.setNextNode(node) ;
  52. node.setPriorNode(this.head);
  53. node.setNextNode(this.head) ;
  54. this.size++ ;
  55. }else if( pos>this.size ){ // pos位置大于链表长度,插入末端
  56. insertNode(node) ;
  57. }else if( pos>0 && pos<=this.size ){ // 链表内节点
  58. // 1、找到要插入位置pos节点,插入pos节点当前位置
  59. int find = 0;
  60. while( find<pos-1 && current.getNextNode()!=this.head ){
  61. current = current.getNextNode() ;
  62. find++ ;
  63. }
  64. // 2、插入节点
  65. if( current.getNextNode()==this.head ){ // 尾节点
  66. node.setPriorNode(current);
  67. node.setNextNode(this.head);
  68. current.setNextNode(node);
  69. } else if( current.getNextNode()!=this.head ) { //中间节点
  70. node.setPriorNode(current.getPriorNode());
  71. node.setNextNode(current);
  72. current.getPriorNode().setNextNode(node);
  73. current.setPriorNode(node);
  74. }
  75. this.size++ ;
  76. }else{
  77. System.out.println("位置信息错误");
  78. flag = false ;
  79. }
  80. return flag;
  81. }
  82.  
  83. private void initLinkList(){
  84. if( size==0 ){
  85. this.head.setNextNode(this.head);
  86. this.head.setPriorNode(this.head);
  87. }
  88. }
  89.  
  90. /*
  91. * 指定链表的节点pos,删除对应节点。方式:找到要删除节点的前后节点删除,下标从1开始
  92. * */
  93. @Override
  94. public boolean deleteNode(int pos) {
  95. boolean flag = false;
  96. DNode current = this.head.getNextNode() ;
  97. if( pos<=0 || pos>this.size || current==this.head ){
  98. System.out.println("位置信息错误或链表不存在");
  99. }else{
  100. // 1、找到要删除位置pos节点
  101. int find = 0;
  102. while( find<pos-1 && current.getNextNode()!=this.head ){
  103. current = current.getNextNode() ;
  104. find++ ;
  105. }
  106. // 2、删除节点
  107. if( current.getNextNode()==this.head ){ // 尾节点
  108. current.getPriorNode().setNextNode(this.head) ;
  109. } else if( current.getNextNode()!=this.head ) { //中间节点
  110. current.getPriorNode().setNextNode(current.getNextNode()) ;
  111. current.getNextNode().setPriorNode(current.getPriorNode()) ;
  112. }
  113. System.gc(); // 回收删除节点
  114. this.size-- ;
  115. flag = true ;
  116. }
  117. return flag;
  118. }
  119.  
  120. /*
  121. * 指定链表的节点pos,修改对应节点,下标从1开始
  122. * */
  123. @Override
  124. public boolean updateNode(int pos, Map<String, Object> map) {
  125. boolean flag = false ;
  126. DNode node = getNode(pos, map);
  127. if( node!=null ){
  128. String data = (String) map.get("data") ;
  129. node.setData(data);
  130. flag = true ;
  131. }
  132. return flag;
  133. }
  134.  
  135. /*
  136. * 找到指定链表的节点pos,下标从1开始
  137. * */
  138. @Override
  139. public DNode getNode(int pos, Map<String, Object> map) {
  140. DNode current = this.head.getNextNode() ;
  141. if( pos<=0 || pos>this.size || current==this.head ){
  142. System.out.println("位置信息错误或链表不存在");
  143. return null;
  144. }
  145. int find = 0 ;
  146. while( find<pos-1 && current!=this.head ){
  147. current = current.getNextNode() ;
  148. find++ ;
  149. }
  150. return current;
  151. }
  152.  
  153. /*
  154. * 打印链表
  155. * */
  156. @Override
  157. public void printLink() {
  158. int length = this.size ;
  159. if( length==0 ){
  160. System.out.println("链表为空!");
  161. return ;
  162. }
  163. DNode current = this.head.getNextNode() ;
  164. int find = 0 ;
  165. System.out.println("总共有节点数: " + length +" 个");
  166. while( current!=this.head ){
  167. System.out.println("第 " + (++find) + " 个节点 :" + current);
  168. current=current.getNextNode() ;
  169. }
  170. }
  171.  
  172. public static void main(String[] args) {
  173. DoubleCycleLinkList dcll = new DoubleCycleLinkList() ;
  174. DNode node1 = new DNode("节点1");
  175. DNode node2 = new DNode("节点2");
  176. DNode node3 = new DNode("节点3");
  177. DNode node4 = new DNode("节点4");
  178. DNode node5 = new DNode("节点5");
  179. DNode node6 = new DNode("插入指定位置");
  180. dcll.insertPosNode(10, node1) ;
  181. dcll.insertPosNode(10, node2) ;
  182. dcll.insertPosNode(8, node3) ;
  183. dcll.insertPosNode(88, node4) ;
  184. dcll.insertPosNode(8, node5) ;
  185. // dcll.insertNode(node1);
  186. // dcll.insertNode(node2);
  187. // dcll.insertNode(node3);
  188. // dcll.insertNode(node4);
  189. // dcll.insertNode(node5);
  190.  
  191. System.out.println("*******************输出链表*******************");
  192. dcll.printLink();
  193.  
  194. System.out.println("*******************获得指定链表节点*******************");
  195. int pos = 2 ;
  196. System.out.println("获取链表第 "+pos+"个位置数据 :"+dcll.getNode(pos, null));
  197.  
  198. System.out.println("*******************向链表指定位置插入节点*******************");
  199. int pos1 = dcll.getSize()+1 ;
  200. System.out.println("将数据插入第"+pos1+"个节点:");
  201. dcll.insertPosNode(pos1, node6) ;
  202. dcll.printLink();
  203.  
  204. System.out.println("*******************删除链表指定位置节点*******************");
  205. int pos2 = 7 ;
  206. System.out.println("删除第"+pos2+"个节点:");
  207. dcll.deleteNode(pos2) ;
  208. dcll.printLink();
  209.  
  210. System.out.println("*******************修改链表指定位置节点*******************");
  211. int pos3 = 3 ;
  212. System.out.println("修改第"+pos3+"个节点:");
  213. Map<String, Object> map = new HashMap<>() ;
  214. map.put("data", "this is a test") ;
  215. dcll.updateNode(pos3, map) ;
  216. dcll.printLink();
  217. }
  218. }

JAVA 链表操作:循环链表的更多相关文章

  1. JAVA 链表操作:单链表和双链表

    主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都 ...

  2. Java链表操作代码

    /** * */ package com.cherish.SwordRefersToOffer; /** * @author acer * */ public class test_22链表中倒数第k ...

  3. Java 链表

    按链表的组织形式分有ArrayList和LinkList两种.ArrayList内部其实是用数组的形式实现链表,比较适合链表大小确定或较少对链表进行增删操作的情况,同时对每个链表节点的访问时间都是co ...

  4. Java链表基本操作和Java.util.ArrayList

    Java链表基本操作和Java.util.ArrayList 今天做了一道<剑指offer>上的一道编程题“从尾到头打印链表”,具体要求如下:输入一个链表,按链表值从尾到头的顺序返回一个A ...

  5. JAVA链表中迭代器的实现

    注:本文代码出自<java数据结构和算法>一书. PS:本文中类的名字定义存在问题,Link9应改为Link.LinkList9应该为LinkList.由于在同包下存在该名称,所以在后面接 ...

  6. linux 内核的链表操作(好文不得不转)

    以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...

  7. Java数组操作的10大方法

    转载自码农网 译文链接:http://www.codeceo.com/article/10-java-array-method.html 英文原文:Top 10 Methods for Java Ar ...

  8. Java链表设计

    链表 1,链表的实现 在实际开发之中对象数组是一项非常实用的技术,并且利用其可以描述出“多”方的概念,例如:一个人有多本书,则在人的类里面一定要提供有一个对象数组保存书的信息,但是传统的对象数组依赖于 ...

  9. Python链表操作(实现)

    Python链表操作 在Python开发的面试中,我们经常会遇到关于链表操作的问题.链表作为一个非常经典的无序列表结构,也是一个开发工程师必须掌握的数据结构之一.在本文中,我将针对链表本身的数据结构特 ...

随机推荐

  1. R in Action 读书笔记(6)基本图形

    MindMapper原文件

  2. [ASP.NET MVC 小牛之路]08 - Area 使用

    ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,每个Area代表应用程序的不同功能模块.这对于大的工程非常有用,Area 使每个功能模块都有各自的文件夹,文件夹中有自己的Cont ...

  3. 查看html元素绑定的事件与方法的利器

    WEB标准提倡结构.表现和行为相 分离,现在越来越多采用这种表现和行为的方式,但它也为我们开发调试带来一些问题,网页载入一堆JavaScript,,我们很难搞清楚最后在哪些元素的哪个动作绑定了事件,尤 ...

  4. iOS-iOS开发简单介绍

    概览 终于到了真正接触IOS应用程序的时刻了,之前我们花了很多时间去讨论C语言.ObjC等知识,对于很多朋友而言开发IOS第一天就想直接看到成果,看到可以运行的IOS程序.但是这里我想强调一下,前面的 ...

  5. Nginx与Apache比较

    Nginx特点:高性能epoll 异步非阻塞多个连接(万级别)可以对应一个进程 支持反向代理支持7层负载均衡静态文件.反向代理.前端缓存等处理方便支持高并发连接,每秒最多的并发连接请求理论可以达到 5 ...

  6. js深浅复制

    一.数组的深浅拷贝 <body> <script type="text/javascript"> var arr = ["One",&q ...

  7. Mysql命令show global status求根溯源

    近来,发现好多公司对mysql的性能监控是通过show global status实现的,因此对于这个命令想要探究一番,看他是否是实时更新的. 在此之前,我们必须搞明白mysql对于这个命令的执行过程 ...

  8. 【原创】开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  9. C语言之通过冒泡排序浅谈编程思想

    写这篇博文的目的是想起到抛砖引玉的作用,还请大牛们留下一些先进的思想,让小菜学习一下.下面入正题. 复习C语言怎么能少的了冒泡呢,记得刚学C语言那会,感觉冒泡排序真的太复杂了,理解不大了,嗯!还是当时 ...

  10. c# 我所理解的 值类型 and 引用类型

    一直以来对于值类型和引用类型都只是一个模糊的概念,趁最近有空深入理解了下. 先说说值类型,在msdn上是这样介绍值类型的. 意思就是值类型直接包含值. 变量引用的位置就是值所在内存中实际存储的位置,所 ...