双向循环链表的Java版本实现
- 1、单项循环列表
单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环。和单链表相比,循环单链表的长处是从链尾到链头比较方便。当要处理的数据元素序列具有环型结构特点时,适合于采用循环单链表。
- 2、单向循环链表
和单链表相同,循环单链表也有带头结点结构和不带头结点结构两种,带头结点的循环单链表实现插入和删除操作时,算法实现较为方便。带头结点的循环单链表结构如下:
带头结点的循环单链表的操作实现方法和带头结点的单链表的操作实现方法类同,差别仅在于:
(1)在构造函数中,要加一条head.next = head 语句,把初始时的带头结点的循环单链表设计成图2-11 (a)所示的状态。
(2)在index(i)成员函数中,把循环结束判断条件current != null改为current != head。
- 双向循环链表
双向链表是每个结点除后继指针外还有一个前驱指针。和单链表类同,双向链表也有带头结点结构和不带头结点结构两种,带头结点的双向链表更为常用;另外,双向链表也可以有循环和非循环两种结构,循环结构的双向链表更为常用。
在双向链表中,每个结点包括三个域,分别是element域、next域和prior域,其中element域为数据元素域,next域为指向后继结点的对象引用,prior域为指向前驱结点的对象引用。
如下图是带头结点的循环双向链表的图示结构。循环双向链表的next和prior各自构成自己的循环单链表。
在双向链表中,有如下关系:设对象引用p表示双向链表中的第i个结点,则p.next表示第i+1个结点,p.next.prior仍表示第i个结点,即p.next.prior == p;同样地,p.prior表示第i-1个结点,p.prior.next仍表示第i个结点,即p.prior.next == p。下图是双向链表上述关系的图示。
循环双向链表的插入过程如下图所示。图中的指针p表示要插入结点的位置,s表示要插入的结点,①、②、③、④表示实现插入过程的步骤。
//==========================================我是代码的分割线
//具体代码的分析已经详细的写在了解析里面,欢迎讨论
/**
* 本项目主要是通过几个类来组合实现
* 1、List的线性表的接口
* 2、Node节点类的具体方法
* 3、单项链表类的具体实现
*/ /**
* 线性表接口
*/
public interface List { // 获得线性表的长度
public int size(); // 判断是否为空
public boolean isEmpty(); // 插入操作,需要抛出异常
public void insert(int index, Object obj) throws Exception; // 删除元素
public void delete(int index) throws Exception; // 获取指定位置元素
public Object get(int index) throws Exception; }
List interface
//节点类
//这个是重点!!!!Java一样可以实现指针的跳转->使用引用
public class Node { Object element; // 数据域
Node next;// 后继指针域
Node prior;// 前驱指针域 // 头节点的构造方法
public Node(Node nextval) {
this.next = nextval;
} // 非头节点的构造方法
public Node(Object obj, Node nextval) {
this.element = obj;
this.next = nextval;
} // 获得当前节点的后继结点
public Node getNext() {
return this.next;
} // 获得当前节点的前驱结点
public Node getPrior() {
return this.prior;
} // 获得当前节点的数据域的值
public Object getElement() {
return this.element;
} // 设置当前节点的后继指针域
public void setNext(Node nextval) {
this.next = nextval;
} // 设置当前节点的前驱指针域
public void setPrior(Node priorval) {
this.prior = priorval;
} // 设置当前节点的数据域,
public void setElement(Object obj) {
this.element = obj;
} public String toString() {
return this.element.toString();
}
}
//单向链表类
public class DoubleCycleLinkList implements List { Node head;// 头指针
Node current;// 当前节点对象
int size; // 节点的个数 // 初始化一个空链表
public DoubleCycleLinkList() {
// 初始化头节点,让头指针指向头节点,并且让当前节点对象等于头节点
this.head = current = new Node(null);
this.size = 0; // 单项链表出事长度为0
// 循环列表属性
this.head.next = head;
this.head.prior = head;
} // 定位函数,实现当前操作对象的前一个节点,也就是让当前节点对象定位到要要操作节点的前一个节点
public void index(int index) throws Exception {
// 参数非法时,出现-1是由于第一个元素的下标是0,而第一个元素的前面就是头节点,该节点就得用-1表示下标了。
if (index < -1 || index > size - 1) {
throw new Exception("参数错误");
}
// 说明是在头节点之后进行操作
if (index == -1)
return;
// 通过该循环获得要操作的那个数的前一个节点
current = head.next;
int j = 0;// 循环变量
// 循环链表属性
while (current != head && j < index) {
current = current.next;
j++;
} } @Override
public int size() {
// TODO Auto-generated method stub
return this.size;
} @Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return size == 0;
} @Override
public void insert(int index, Object obj) throws Exception {
// TODO Auto-generated method stub
// 可以等于0表示在一个元素的前面插入,也就是头结点的后面
if (index < 0 || index > size) {
throw new Exception("参数错误! ");
}
/**
* 这里是核心操作
*/
// 定位到要操作节点的前一个节点对象
index(index - 1);
// 将前一个节点进行设置,使其指向要插入节点的指针域,
current.setNext(new Node(obj, current.next));
size++;
} @Override
public void delete(int index) throws Exception {
// TODO Auto-generated method stub
if (isEmpty()) {
throw new Exception("链表为空,无法删除");
} if (index < 0 || index > size) {
throw new Exception("参数错误!");
}
// 进行定位
index(index - 1);
// current此时表示要删除节点的前一个节点的指示,因此需要将该节点指向要删除的那个节点的下一个节点才对
// 修改后继指针
current.setNext(current.next.next);
// 修改前驱指针
current.next.setPrior(current);
size--; } @Override
public Object get(int index) throws Exception {
// TODO Auto-generated method stub
if (index < -1 || index > size - 1) {
throw new Exception("参数非法,无法查询");
}
// 先定位
index(index);
return current;
}
}
//测试类
public class Test {
public static void main(String[] args) throws Exception {
DoubleCycleLinkList list = new DoubleCycleLinkList();
for (int i = 0; i < 10; i++) {
// 0-99之间的整数
int temp = (int) (Math.random() * 100);
list.insert(i, temp);
System.out.print(temp + " ");
} list.delete(4);
System.out.println();
System.out.println("----删除第五个元素之后------");
for (int i = 0; i < list.size; i++) {
System.out.print(list.get(i) + " ");
}
}
}
双向循环链表的Java版本实现的更多相关文章
- 3.1、双向循环链表(java实现)
1.创建节点类 public class CNode<T> { public CNode prev; public CNode next; public T data; public CN ...
- java与数据结构(4)---java实现双向循环链表
线性表之链式存储结构双向循环链表 双向循环链表:每个结点包含了数据.直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环.可以形象 ...
- java实现双向循环链表
java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...
- (java实现)双向循环链表
什么是双向循环链表 在了解双向循环链表之前,如果对链表还没有一个清晰的概念,建议你看看单链表和单向循环链表,这有利于你更好的理解下面的内容.(废话有点多[逃] 相比单链表,双向循环链表是一个更加复杂的 ...
- Java 用双向循环链表实现 遍历
package day2; /** * 构建双向循环链表,实现遍历功能 */public class DoubleLB { public static void main(String[] args) ...
- java数据结构-06双向循环链表
双向循环链表跟单向链表一样,都是头尾相连,不过单向是尾指向头,双向是头尾互相指,可以从前往后查,也可以从后往前查 无头结点的双向循环链表 public class CircleLinkedList&l ...
- C语言通用双向循环链表操作函数集
说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低. 可基于该函数集方便地构造栈或队列集. 本函数集暂未考虑并发保护. 一 ...
- "《算法导论》之‘线性表’":双向循环链表
本文双链表介绍部分参考自博文数组.单链表和双链表介绍 以及 双向链表的C/C++/Java实现. 1 双链表介绍 双向链表(双链表)是链表的一种.和单链表一样,双链表也是由节点组成,它的每个数据结点中 ...
- Linux内核2.6.14源码分析-双向循环链表代码分析(巨详细)
Linux内核源码分析-链表代码分析 分析人:余旭 分析时间:2005年11月17日星期四 11:40:10 AM 雨 温度:10-11度 编号:1-4 类别:准备工作 Email:yuxu97101 ...
随机推荐
- Hibernate检索策略之延迟加载和立即加载
延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询.避免了无谓的性能开销. 延迟加载分类: 1.类级别的查询策略 2.一对多和多对多关联的查询策略 3.多对 ...
- 简单工程使用sbt公共库(sbt-assembly)
只是为了简单实现一个算法,想用到breeze算法库.想把breeze当做external libraryies直接导入工程.可是官网没有,网上搜索更多的是在sbt工程或maven工程下. 后来实现目标 ...
- c#语句 for循环嵌套
1.打印三角形. 1) 方法一.for嵌套 方法二.只用一个for 2)倒三角 3)后三角 2.求100以内质数的和. 3.一张纸厚度为0.01米,至少对折多少次才能达到珠峰的高度?(用for死循环) ...
- jdbc中java与mysql数据类型的映射
注:这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配.例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日.
- jetBrains phpstorm/webstorm 编辑器使用诀窍
下载地址 https://www.jetbrains.com/products.html?fromMenu CTRL + F12 / COMMAND + F12 打开类中的结构 Ctrl + b / ...
- Java接入图灵机器人,实现与机器人聊天
很多人都玩过微信,其中就有与机器人聊天的功能:
- UFS
● UFS vs eMMC 1. UFS有分离的读写通道,可以同时进行读写操作(双向),但是eMMC在同一时刻只能读或写. 2. UFS有一个命令队列,将命令进行排序.因此,多个命令可以同时处理,从而 ...
- MVC4脚本压缩 BundleTable bundles 404错误
在发布网站的时候,因为使用了MVC4的新特性BundleTable,造成访问的时候js和css报了404错误, google了以后, 有朋友说是因为要在webservice添加 <modules ...
- 20145209&20145309信息安全系统设计基础实验报告 (4)
实验步骤 阅读和理解源代码 demo_read,demo_write 函数完成驱动的读写接口功能,do_write 函数实现将用户写入的数据逆序排列,通过读取函数读取转换后的数据.这里只是演示接口的实 ...
- 带你玩转JavaWeb开发之三 - CSS从基础到实战
一,什么是CSS? Cascading Style Sheets层叠样式表 层叠:就是层层覆盖叠加,如果有多种样式对同一html标签进行修饰,样式有冲突的部分应用优先级高,不冲突的 ...