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开发的面试中,我们经常会遇到关于链表操作的问题.链表作为一个非常经典的无序列表结构,也是一个开发工程师必须掌握的数据结构之一.在本文中,我将针对链表本身的数据结构特 ...
随机推荐
- Jmeter 使用Jmeter与Badboy进行压力测试
1. 介绍 Badboy是一个录制请求的工具,这里用它来生成文件给JMeter用. JMeter是一个用java写的开源的性能测试工具,用于模拟在服务器.网络或者其他对象上附加高负载以测试他们提供服务 ...
- python & mongo问题记录
背景介绍 使用python操作mongo进行的一些操作记录,为了方便日后可以快速的解决类似问题. 准备工作 为了尽可能简单的说明,我将插入几条简单的数据. from pymongo import Mo ...
- android/java 根据当前时间判断股票交易状态(未开盘 交易中 休市中 已收盘)
/** * @param data yyyy-MM-dd HH:mm:ss 时间 * @return 未开盘 交易中 休市中 已收盘 */ public static String getSotckS ...
- 无法在“EntityFramework”已存在的情况下创建影像复制该文件的解决方案
问题产生的原因:你项目正在生成中你就打开浏览器预览了,导致这个问题解决方案:右击重新生成项目,等生成后再打开 “/”应用程序中的服务器错误. 无法在“EntityFramework”已存在的情况下创建 ...
- Android 圆形头像 自己动手
圆形头像DIY 现在大部分app使用的都是圆形头像,网上开源的也很多,但是有没有考虑过DIY圆形头像呢?下面就自己实现一个,先看下demo展示 第一步:原理解释(图片很丑,原理很真) 1.画外框圆形, ...
- MVC5 网站开发实践 2.1、管理员登陆
目录 MVC5 网站开发实践 概述 MVC5 网站开发实践 1.建立项目 MVC5 网站开发实践 2.后台管理 1. 创建SHA256加密方法. 在Data项目中添加文件夹[Security ...
- @font-face使用
转自http://www.tuicool.com/articles/QVf6nei 一.webfont与@font-face 什么是webfont web font,又称之为 在线字体 或者 网络字体 ...
- Util应用程序框架公共操作类(六):验证扩展
前面介绍了仓储的基本操作,下面准备开始扩展查询,在扩展查询之前,首先要增加两个公共操作类,一个是经常要用到的验证方法,另一个是Lambda表达式的操作类. 很多时候,我们会判断一个对象是否为null, ...
- MySQL学习笔记四:字符集
1.字符集就是字符和其编码的集合,查看数据库支持的字符集 show character set 2.查看服务端启动时默认的字符集 mysql> show variables like 'char ...
- T-SQL:毕业生出门需知系列(五)
第5课 高级数据过滤 5.1 组合 WHERE 子句 第4课介绍的 WHERE 子句在过滤数据时都是用单一的条件. 5.1.1 AND 操作符 检索由供应商 DLL01 制造且价格小于等于 4 美元的 ...