Java数据结构——循环链表
一、单向循环链表
表中的最后一个节点的指针域指向头结点,整个链表形成一个环。其他的与单链表相同。
(以下图片均来自网络,侵删)

插入操作

删除操作

简单实现
public class CiNode {
private Object data;
private CiNode next;
private static CiNode first; // 临时结点,头结点,并不是链表里想要的值,起到标记链表头的作用
public CiNode() {
super();
}
public CiNode(Object data, CiNode next) {
super();
this.data = data;
this.next = next;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public CiNode getNext() {
return next;
}
public void setNext(CiNode next) {
this.next = next;
}
public static void add(CiNode node, int index) {
if (index == 0) {
node.next = first.next;
first.next = node;
} else {
int temp = 0;
for (CiNode n = first.next;; n = n.next) {
temp++;
if (temp == index) {
node.next = n.next;
n.next = node;
break;
}
}
}
}
public static void remove(int index) {
if (index % 5 == 0) { // 删除第一个元素,考虑循环
first.next = first.next.next;
} else {
int temp = 0;
for (CiNode n = first.next;; n = n.next) {
if (n == first) {
temp -= 1; // 减一是因为链表循环计数时会把first记一次,所以这里减一次,使下标一致
}
temp++;
if (temp == index) {
n.next = n.next.next;
break;
}
}
}
}
public static void display() {
for (CiNode n = first.next; n != first; n = n.next) {
System.out.print(n.data + " ");
}
System.out.println();
}
public static void main(String[] args) {
CiNode node4 = new CiNode("ddd", null);
CiNode node3 = new CiNode("ccc", node4);
CiNode node2 = new CiNode("bbb", node3);
CiNode node1 = new CiNode("aaa", node2);
first = new CiNode(null, node1);
node4.next = first;
System.out.println("当前链表:");
display();
add(new CiNode("eee", null), 5); // 传5进去是为了体现循环,当参数大于了链表长度时,又回到first
System.out.println("插入后链表:");
display();
remove(11);
System.out.println("删除后链表:");
display();
}
}
循环单链表模拟击鼓传花游戏
public class JiGuChuanHua implements Runnable {
private Object person;//游戏的人的data
private JiGuChuanHua next;//指向下一个人,
private static JiGuChuanHua first;//第一个人
public JiGuChuanHua() {
super();
}
//构造方法
public JiGuChuanHua(Object person, JiGuChuanHua next) {
super();
this.person = person;
this.next = next;
}
@Override
public void run() {
JiGuChuanHua loser = first; //以第一个人为起点
double time = (Math.random() + 0.5) * 10; //随机产生游戏时间(5-15s)
boolean flag = true;//结束线程的标志
System.out.println("本局游戏时间:" + time + "s");
System.out.println("游戏开始:");
System.out.println(loser.person);//初始游戏时,花在第一个人手上,打印
double startTime = System.currentTimeMillis();//获取开始游戏的时间
while (flag) {
for (JiGuChuanHua node = first;; node = node.next) {
loser = node.next;//loser指向下一个人,模拟传花过程
System.out.println(loser.person);//打印拿到花的人
try {
Thread.sleep((long) (Math.random() * 500));//线程睡眠,模拟花在每一个人手中停留时间
} catch (InterruptedException e) {
e.printStackTrace();
}
double endTime = System.currentTimeMillis();//传完一个人时的时间
if (endTime - startTime >= time * 1000) {//游戏时间到,这里不具备原子性,所以是大于等于
flag = false;//标志位置为false
break;
}
}
}
System.out.println("游戏结束,拿到花的人是:" + loser.person);//打印最后拿到花的人
}
public static void main(String[] args) {
//将参加游戏的人用链表连起来,构成一个循环
JiGuChuanHua person5 = new JiGuChuanHua("e", null);
JiGuChuanHua person4 = new JiGuChuanHua("d", person5);
JiGuChuanHua person3 = new JiGuChuanHua("c", person4);
JiGuChuanHua person2 = new JiGuChuanHua("b", person3);
JiGuChuanHua person1 = new JiGuChuanHua("a", person2);
person5.next = person1;
first = person1;
JiGuChuanHua jgch = new JiGuChuanHua();
Thread thread = new Thread(jgch);
thread.start(); //开启线程
}
}
二、双向循环链表
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

插入操作

删除操作

简单实现
public class CiDlNode {
private Object data;
private CiDlNode next;
private CiDlNode prev;
private static CiDlNode first;
public CiDlNode() {
super();
}
public CiDlNode(Object data, CiDlNode next, CiDlNode prev) {
super();
this.data = data;
this.next = next;
this.prev = prev;
}
public static void insert(Object data, int index) {
CiDlNode node = new CiDlNode(data, null, null);
if (index == 0) {
node.next = first.next;
first.next.prev = node;
first.next = node;
node.prev = first;
} else {
int temp = 0;
for (CiDlNode n = first.next;; n = n.next) {
temp++;
if (temp == index) {
node.next = n.next;
node.next = n.next;
n.next.prev = node;
n.next = node;
node.prev = n;
break;
}
}
}
}
public static void remove(Object data) {
for (CiDlNode n = first.next; n != first; n = n.next) {
if (n.data.equals(data)) {
n.prev.next = n.next;
n.next.prev = n;
}
}
}
public static void print() {
for (CiDlNode node = first.next; node != first; node = node.next) {
System.out.print(node.data + " ");
}
System.out.println();
}
public static void main(String[] args) {
first = new CiDlNode("0", null, null);
CiDlNode node1 = new CiDlNode("aaa", null, first);
CiDlNode node2 = new CiDlNode("bbb", null, node1);
CiDlNode node3 = new CiDlNode("ccc", null, node2);
CiDlNode node4 = new CiDlNode("ddd", first, node3);
node3.next = node4;
node2.next = node3;
node1.next = node2;
first.next = node1;
System.out.println("当前链表:");
print();
insert("ddd", 5);
System.out.println("插入后链表:");
print();
remove("ddd");
System.out.println("删除后链表:");
print();
}
}
Java数据结构——循环链表的更多相关文章
- Java数据结构——循环链表的实现
//单链表结点类 public class Node<T> { //单链表结点类,T指定结点的元素类型 public T data; //数据域,保存数据元素 public Node< ...
- java与数据结构(3)---java实现循环链表
循环链表:将单链表中尾结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种首尾相接的单链表称为单链表循环表,即循环链表. 循环链表与单链表最重要的区别是:尾结点的指针,不再是p->n ...
- Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
Java数据结构之---Queue队列 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在 ...
- Java数据结构之线性表(2)
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- Java数据结构之线性表
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- Java数据结构和算法(一)线性结构
Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...
- JAVA数据结构系列 栈
java数据结构系列之栈 手写栈 1.利用链表做出栈,因为栈的特殊,插入删除操作都是在栈顶进行,链表不用担心栈的长度,所以链表再合适不过了,非常好用,不过它在插入和删除元素的时候,速度比数组栈慢,因为 ...
- Java数据结构之树和二叉树(2)
从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...
- Java数据结构之树和二叉树
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
随机推荐
- 第二章 Java基础知识(上)
2.1.注释 单行注释 // 注释内容 多行注释 /* 注释内容 */ 文档注释 /**注释内容 */ 2.2.关键字 定义:在Java语言中被赋予特殊含义的小写单词 分类: 2.3.标识符 定义:标 ...
- java反序列化——apache-shiro复现分析
本文首发于“合天智汇”公众号 作者:Fortheone 看了好久的文章才开始分析调试java的cc链,这个链算是java反序列化漏洞里的基础了.分析调试的shiro也是直接使用了cc链.首先先了解一些 ...
- PHP 怎么安装
您需要做什么? 为了开始使用 PHP,您可以: 找一个支持 PHP 和 MySQL 的 Web 主机 在您自己的 PC 机上安装 Web 服务器,然后安装 PHP 和 MySQL 使用支持 PHP 的 ...
- TCP为什么做三次握手、四次挥手
TCP 为什么做三次握手.四次挥手? TCP 是为了解决可靠传输出现的.为了实现可靠性,TCP 做了流量控制.拥塞控制,并且在建立.关闭连接前做些机制:三次握手.四次挥手. 三次握手是为了让客户端.服 ...
- Docker这些none:none的镜像,难道就不配拥有名字吗
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 搞容器开发一段时间后,想看看都有哪些镜像,执行了一下docker images -a,蒙圈了,有一堆<none> ...
- Caffe CuDNN版本与环境不同导致make错误
1.将./include/caffe/util/cudnn.hpp 换成最新版的caffe里的cudnn的实现,即相应的cudnn.hpp. 2.将./include/caffe/layers里的,所 ...
- python基础语法和实战练习
(一)Python基础学习 Num01:python的基本数据类型 ①字符串:可进行拼接和截取 ②数字:int,float,complex(复数) 涉及到格式转换:int(x)转换为整数,float( ...
- VMware启动CentOS出错,提示"该虚拟机似乎正在使用中"
今天在使用VMware启动CentOS时,出现如下图1错误提示: 当点击“确定”按钮时,出现如下图2错误提示: 无奈,只能点击图1 中的“取消”按钮,进行问题的跟踪.分析.经过核实,发现上述问题是由于 ...
- day27:异常&反射
目录 认识异常处理 1.程序错误的种类 2.异常的分类 3.AssertionError(断言assert语句失败) 异常处理的基本语法 1.异常处理的基本语法 2.带有分支的异常处理 3.处理 ...
- 栈及其简单应用(python代码)
栈属于线性结构(Linear Struncture),要搞清楚这个概念,首先要明白”栈“原来的意思,如此才能把握本质."栈“者,存储货物或供旅客住宿的地方,可引申为仓库.中转站,所以引入到计 ...