JAVA 链表操作:循环链表
主要分析示例:
一、循环链表简述
二、单链表循环链表
三、双链表循环链表
一、循环链表简述
循环链表即链表形成了一个循环的结构,尾节点不再指向NULL,而是指向头节点HEAD,此时判定链表的结束是尾节点是否指向了头节点HEAD。基本结构为:

备注:其中单链表节点和双链表节点类和接口ICommOperate<T>与上篇一致,这里不在赘述。参考:JAVA链表操作:单链表和双链表http://www.cnblogs.com/xiaoxing/p/5969133.html
二、单链表循环链表
package LinkListTest;
import java.util.HashMap;
import java.util.Map;
public class SingleCycleLinkList implements ICommOperate<SNode> {
private SNode head = new SNode("HEAD") ; // 公共头指针,声明之后不变
private int size = 0 ;
public int getSize() {
return this.size;
} /*
* 链表插入,每次往末端插入,判定末端的标准为next是否指向head
* */
@Override
public boolean insertNode(SNode node) {
boolean flag = false ; initLinkList() ; // 初始化链表
if( this.size==0 ){ // 空链表
this.head.setNextNode(node) ;
node.setNextNode(this.head) ;
}else{
SNode current = this.head ;
while( current.getNextNode()!=this.head ){ // 找到末端节点
current = current.getNextNode() ;
}
current.setNextNode(node) ;
node.setNextNode(this.head) ; // 循坏链表,尾节点指向head
}
this.size++ ;
flag = true ; return flag;
} /*
* 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
* */
@Override
public boolean insertPosNode(int pos, SNode node) {
boolean flag = true ;
SNode current = this.head.getNextNode() ; initLinkList() ;// 初始化链表
if( this.size==0 ){ // 链表为空
this.head.setNextNode(node) ;
node.setNextNode(this.head) ;// 循坏链表,尾节点指向head
this.size++ ;
}else if( this.size<pos ){ // pos位置大于链表长度,插入末端
insertNode(node) ;
}else if( pos>0 && pos<=this.size ){ // 链表内节点
// 1、找到要插入pos位置节点和前节点,node将插入两个节点之间
int find = 0;
SNode preNode = this.head; // 前节点
SNode currentNode = current; // 当前节点
while( find<pos-1 && currentNode!=this.head ){
preNode = current ; // 前节点后移
currentNode = currentNode.getNextNode() ; // 当前节点后移
find++ ;
if( find<pos-1 && currentNode!=this.head ){ // 未结束寻找节点前,后移前节点
current = current.getNextNode() ;
}
}
// System.out.println(preNode);
// System.out.println(currentNode); // 2、插入节点
preNode.setNextNode(node);
node.setNextNode(currentNode);
this.size++ ;
}else {
System.out.println("位置信息错误");
flag = false ;
} return flag;
} private void initLinkList(){
if( size==0 ){
this.head.setNextNode(this.head);
}
} /*
* 指定链表的节点pos,删除对应节点。方式:找到要删除节点的前后节点,进行删除,下标从1开始
* */
@Override
public boolean deleteNode(int pos) {
boolean flag = false;
SNode current = this.head.getNextNode() ;
if( pos<=0 || pos>this.size || current==this.head ){
System.out.println("位置信息错误或链表无信息");
}else{
// 1、找到要删除节点的前后节点
int find = 0;
SNode preNode = this.head; // 前节点
SNode nextNode = current.getNextNode(); // 后节点
while( find<pos-1 && nextNode!=this.head ){
preNode = current ; // 前节点后移
nextNode = nextNode.getNextNode() ; // 后节点后移
find++ ;
if( find<pos-1 && nextNode!=this.head ){ // 未结束找节点前,后移"前节点"
current = current.getNextNode() ;
}
}
// System.out.println(preNode);
// System.out.println(nextNode); // 2、删除节点
preNode.setNextNode(nextNode);
System.gc(); // 回收删除节点
this.size-- ;
flag = true ;
} return flag;
} /*
* 指定链表的节点pos,修改对应节点,下标从1开始
* */
@Override
public boolean updateNode(int pos, Map<String, Object> map) {
boolean flag = false ;
SNode node = getNode(pos, map); // 获得相应位置pos的节点
if( node!=null ){
String data = (String) map.get("data") ;
node.setData(data);
flag = true ;
}
return flag;
} /*
* 找到指定链表的节点pos,下标从1开始
* */
@Override
public SNode getNode(int pos, Map<String, Object> map) {
SNode current = this.head.getNextNode() ;
if( pos<=0 || pos>this.size || current==this.head ){
System.out.println("位置信息错误或链表不存在");
return null;
}
int find = 0 ;
while( find<pos-1 && current!=this.head ){
current = current.getNextNode() ;
find++ ;
}
return current;
} /*
* 打印链表
* */
@Override
public void printLink() {
int length = this.size ;
if( length==0 ){
System.out.println("链表为空!");
return ;
}
SNode current = this.head.getNextNode() ;
System.out.println("总共有节点数: " + length +" 个");
int find = 0 ;
while( current!=this.head ){
System.out.println("第 " + (++find) + " 个节点 :" + current);
current=current.getNextNode() ;
}
} public static void main(String[] args) {
SingleCycleLinkList scll = new SingleCycleLinkList() ;
SNode node1 = new SNode("节点1");
SNode node2 = new SNode("节点2");
SNode node3 = new SNode("节点3");
SNode node4 = new SNode("节点4");
SNode node5 = new SNode("节点5");
SNode node6 = new SNode("插入指定位置");
// scll.insertPosNode(scll.getSize()+1, node1) ;
// scll.insertPosNode(scll.getSize()+1, node2) ;
// scll.insertPosNode(scll.getSize()+1, node3) ;
// scll.insertPosNode(scll.getSize()+1, node4) ;
// scll.insertPosNode(scll.getSize()+1, node5) ;
scll.insertNode(node1);
scll.insertNode(node2);
scll.insertNode(node3);
scll.insertNode(node4);
scll.insertNode(node5); System.out.println("*******************输出链表*******************");
scll.printLink(); System.out.println("*******************获得指定链表节点*******************");
int pos = 2 ;
System.out.println("获取链表第 "+pos+" 个位置数据 :"+scll.getNode(pos, null)); System.out.println("*******************向链表指定位置插入节点*******************");
int pos1 = 3 ;
System.out.println("将数据插入第"+pos1+"个节点:");
scll.insertPosNode(pos1, node6) ;
scll.printLink(); System.out.println("*******************删除链表指定位置节点*******************");
int pos2 = 3 ;
System.out.println("删除第"+pos2+"个节点:");
scll.deleteNode(pos2) ;
scll.printLink(); System.out.println("*******************修改链表指定位置节点*******************");
int pos3 = 3 ;
System.out.println("修改第"+pos3+"个节点:");
Map<String, Object> map = new HashMap<>() ;
map.put("data", "this is a test") ;
scll.updateNode(pos3, map) ;
scll.printLink();
} }
三、双链表循环链表
package LinkListTest; import java.util.HashMap;
import java.util.Map; public class DoubleCycleLinkList implements ICommOperate<DNode>{
private DNode head = new DNode("HEAD"); // 公共头指针,声明之后不变
private int size = 0 ; // 记录链表节点数量 public int getSize() {
return this.size;
} /*
* 链表插入,每次往末端插入,判定末端的标准为next是否指向head
* */
@Override
public boolean insertNode(DNode node) {
boolean flag = false ; initLinkList() ; // 初始化链表
DNode current = this.head ;
if( this.size==0 ){ // 空链表
this.head.setNextNode(node) ;
node.setPriorNode(this.head);
node.setNextNode(this.head) ;
}else{ // 链表内节点
while( current.getNextNode()!=this.head ){ // 找到末端节点
current = current.getNextNode() ;
}
current.setNextNode(node) ;
node.setPriorNode(current);
node.setNextNode(this.head) ; // 循坏链表,尾节点指向head
}
this.size++ ;
flag = true ; return flag;
} /*
* 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
* */
@Override
public boolean insertPosNode(int pos, DNode node) {
boolean flag = true; initLinkList() ; // 初始化链表
DNode current = this.head.getNextNode() ;
if( this.size==0 ){ // 链表为空
this.head.setNextNode(node) ;
node.setPriorNode(this.head);
node.setNextNode(this.head) ;
this.size++ ;
}else if( pos>this.size ){ // pos位置大于链表长度,插入末端
insertNode(node) ;
}else if( pos>0 && pos<=this.size ){ // 链表内节点
// 1、找到要插入位置pos节点,插入pos节点当前位置
int find = 0;
while( find<pos-1 && current.getNextNode()!=this.head ){
current = current.getNextNode() ;
find++ ;
}
// 2、插入节点
if( current.getNextNode()==this.head ){ // 尾节点
node.setPriorNode(current);
node.setNextNode(this.head);
current.setNextNode(node);
} else if( current.getNextNode()!=this.head ) { //中间节点
node.setPriorNode(current.getPriorNode());
node.setNextNode(current);
current.getPriorNode().setNextNode(node);
current.setPriorNode(node);
}
this.size++ ;
}else{
System.out.println("位置信息错误");
flag = false ;
}
return flag;
} private void initLinkList(){
if( size==0 ){
this.head.setNextNode(this.head);
this.head.setPriorNode(this.head);
}
} /*
* 指定链表的节点pos,删除对应节点。方式:找到要删除节点的前后节点删除,下标从1开始
* */
@Override
public boolean deleteNode(int pos) {
boolean flag = false;
DNode current = this.head.getNextNode() ;
if( pos<=0 || pos>this.size || current==this.head ){
System.out.println("位置信息错误或链表不存在");
}else{
// 1、找到要删除位置pos节点
int find = 0;
while( find<pos-1 && current.getNextNode()!=this.head ){
current = current.getNextNode() ;
find++ ;
}
// 2、删除节点
if( current.getNextNode()==this.head ){ // 尾节点
current.getPriorNode().setNextNode(this.head) ;
} else if( current.getNextNode()!=this.head ) { //中间节点
current.getPriorNode().setNextNode(current.getNextNode()) ;
current.getNextNode().setPriorNode(current.getPriorNode()) ;
}
System.gc(); // 回收删除节点
this.size-- ;
flag = true ;
}
return flag;
} /*
* 指定链表的节点pos,修改对应节点,下标从1开始
* */
@Override
public boolean updateNode(int pos, Map<String, Object> map) {
boolean flag = false ;
DNode node = getNode(pos, map);
if( node!=null ){
String data = (String) map.get("data") ;
node.setData(data);
flag = true ;
}
return flag;
} /*
* 找到指定链表的节点pos,下标从1开始
* */
@Override
public DNode getNode(int pos, Map<String, Object> map) {
DNode current = this.head.getNextNode() ;
if( pos<=0 || pos>this.size || current==this.head ){
System.out.println("位置信息错误或链表不存在");
return null;
}
int find = 0 ;
while( find<pos-1 && current!=this.head ){
current = current.getNextNode() ;
find++ ;
}
return current;
} /*
* 打印链表
* */
@Override
public void printLink() {
int length = this.size ;
if( length==0 ){
System.out.println("链表为空!");
return ;
}
DNode current = this.head.getNextNode() ;
int find = 0 ;
System.out.println("总共有节点数: " + length +" 个");
while( current!=this.head ){
System.out.println("第 " + (++find) + " 个节点 :" + current);
current=current.getNextNode() ;
}
} public static void main(String[] args) {
DoubleCycleLinkList dcll = new DoubleCycleLinkList() ;
DNode node1 = new DNode("节点1");
DNode node2 = new DNode("节点2");
DNode node3 = new DNode("节点3");
DNode node4 = new DNode("节点4");
DNode node5 = new DNode("节点5");
DNode node6 = new DNode("插入指定位置");
dcll.insertPosNode(10, node1) ;
dcll.insertPosNode(10, node2) ;
dcll.insertPosNode(8, node3) ;
dcll.insertPosNode(88, node4) ;
dcll.insertPosNode(8, node5) ;
// dcll.insertNode(node1);
// dcll.insertNode(node2);
// dcll.insertNode(node3);
// dcll.insertNode(node4);
// dcll.insertNode(node5); System.out.println("*******************输出链表*******************");
dcll.printLink(); System.out.println("*******************获得指定链表节点*******************");
int pos = 2 ;
System.out.println("获取链表第 "+pos+"个位置数据 :"+dcll.getNode(pos, null)); System.out.println("*******************向链表指定位置插入节点*******************");
int pos1 = dcll.getSize()+1 ;
System.out.println("将数据插入第"+pos1+"个节点:");
dcll.insertPosNode(pos1, node6) ;
dcll.printLink(); System.out.println("*******************删除链表指定位置节点*******************");
int pos2 = 7 ;
System.out.println("删除第"+pos2+"个节点:");
dcll.deleteNode(pos2) ;
dcll.printLink(); System.out.println("*******************修改链表指定位置节点*******************");
int pos3 = 3 ;
System.out.println("修改第"+pos3+"个节点:");
Map<String, Object> map = new HashMap<>() ;
map.put("data", "this is a test") ;
dcll.updateNode(pos3, map) ;
dcll.printLink();
}
}
JAVA 链表操作:循环链表的更多相关文章
- JAVA 链表操作:单链表和双链表
主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都 ...
- Java链表操作代码
/** * */ package com.cherish.SwordRefersToOffer; /** * @author acer * */ public class test_22链表中倒数第k ...
- Java 链表
按链表的组织形式分有ArrayList和LinkList两种.ArrayList内部其实是用数组的形式实现链表,比较适合链表大小确定或较少对链表进行增删操作的情况,同时对每个链表节点的访问时间都是co ...
- Java链表基本操作和Java.util.ArrayList
Java链表基本操作和Java.util.ArrayList 今天做了一道<剑指offer>上的一道编程题“从尾到头打印链表”,具体要求如下:输入一个链表,按链表值从尾到头的顺序返回一个A ...
- JAVA链表中迭代器的实现
注:本文代码出自<java数据结构和算法>一书. PS:本文中类的名字定义存在问题,Link9应改为Link.LinkList9应该为LinkList.由于在同包下存在该名称,所以在后面接 ...
- linux 内核的链表操作(好文不得不转)
以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...
- Java数组操作的10大方法
转载自码农网 译文链接:http://www.codeceo.com/article/10-java-array-method.html 英文原文:Top 10 Methods for Java Ar ...
- Java链表设计
链表 1,链表的实现 在实际开发之中对象数组是一项非常实用的技术,并且利用其可以描述出“多”方的概念,例如:一个人有多本书,则在人的类里面一定要提供有一个对象数组保存书的信息,但是传统的对象数组依赖于 ...
- Python链表操作(实现)
Python链表操作 在Python开发的面试中,我们经常会遇到关于链表操作的问题.链表作为一个非常经典的无序列表结构,也是一个开发工程师必须掌握的数据结构之一.在本文中,我将针对链表本身的数据结构特 ...
随机推荐
- MySQL mysqlslap压测
200 ? "200px" : this.width)!important;} --> 介绍 mysqlslap是mysql自带的一个性能压测工具:mysqlslap用于和其 ...
- windows命令——taskmgr 1
taskmgr.exe用于任务管理器.它显示系统中正在运行的进程. 该程序使用Ctrl+Alt+Del(一般是弹出Windows安全再点击“任务管理器”)或者Ctrl+Shift+Esc 有时候需要, ...
- 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)
界面的显示方面就都讲完啦,下面来介绍下控件的响应. 前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEG ...
- jdk1.7.0_80源码包结构
解压源码src.zip,jdk源码结构如下所示: src |--com.sun sun公司对jdk的实现,Oracle官方不支持,不保证跨平台(可能一些类linux有而windows没有),甚至 ...
- Derived Column 用法
Derived Column Component 用法是为数据流增加派生列,Derived column 有两种用法:add as new column 或 replace . 图中,增加一个 De ...
- Entity Framework 6 Code First新特性:支持存储过程
Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作. Code First的插入/修改/删除存储过程 默 ...
- Create Volume 操作(Part I) - 每天5分钟玩转 OpenStack(50)
前面已经学习了 Cinder 的架构和相关组件,从本节我们开始详细分析 Cinder 的各种操作,首先讨论 Cinder 如何创建 volume. Create 操作流程如下: 客户(可以是 Open ...
- java后台搭建学习计划
1. 使用maven管理java项目 2.linux安装mysql 3.linux安装redis 4. mybatis使用demo 5. cannal使用demo 6. 用spring4开发rest应 ...
- Google Chrome 应用商店上传扩展程序
1. 进入 Google 开发者中心 网址: https://chrome.google.com/webstore/developer/dashboard?hl=zh-cn 2. 添加新项 上传后,出 ...
- IDDD 实现领域驱动设计-SOA、REST 和六边形架构
上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(State) 六边形架构 DDD ...