线性表之链式存储结构双向循环链表

双向循环链表:每个结点包含了数据、直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环。可以形象的理解成一群孩子手拉手牵成一个圆圈,从头一个孩子开始可以从左往右报数,也可以从右往左开始报数。

优点:双向循环链表可以迅速的获取当前数据的前驱数据,解决了单向循环链表从头开始遍历的麻烦。

接口类

 package list;

 public interface Listable<T> {

     public void clear();

     public boolean isEmpty();

     public int Length();

     public T getElement(int index);

     public boolean add(T element);

     public boolean addHead(T element);

     public boolean addByIndex(int index, T element);

     public boolean add(Listable<T> list);

     public T remove(int index);

     public boolean removeAll();

     public T remove(T element);

     public T setElement(int index,T element);

 }

结点类

 //结点类
class Node<T> {
private Node<T> left,right;
private T data; Node(T data) {
this(data,null,null);
} Node() {
this(null,null,null);
} Node(T data,Node<T> left,Node<T> right) {
this.data = data;
this.left = left;
this.right = right;
} public T getData() {
return this.data;
} public Node<T> getLeft() {
return this.left;
} public Node<T> getRight() {
return this.right;
} public void setData(T data) {
this.data = data;
} public void setRight(Node<T> right) {
this.right = right;
} public void setLeft(Node<T> left) {
this.left = left;
} public String toString() {
return getData().toString();
}
}

接口实现类

 //接口实现类
class DoubleLinkedList<T> implements Listable<T> {
public Node<T> head; //建空表,带头结点
DoubleLinkedList() {
this(null);
} //建表,带头结点,表中有一条数据元素
DoubleLinkedList(T element) {
if(element == null) {
head = new Node<T>(element,null,null);
head.setRight(head);
head.setLeft(head);
}else {
Node<T> headRight = new Node<T>(element,null,null);
head = new Node<T>(null,headRight,headRight);
headRight.setLeft(head);
headRight.setRight(head);
}
} //清空当前链表
public void clear() {} //判空表
public boolean isEmpty() {
return head.getRight() == head;
} //表长
public int Length() {
int len = 0;
Node<T> temp = head;
while(temp.getRight() != head) {
len++;
temp = temp.getRight();
}
return len;
} //取下标index处的数据
public T getElement(int index) {
if(index <= 0) {
return head.getRight().getData();
}
int len = Length();
if(index >= len) {
return head.getLeft().getData();
}
T element = null;
if(index > 0 && index < len) {
int k = 0;
Node<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
element = temp.getData();
}
return element;
} //尾添
public boolean add(T element) {
if(element == null) return false;
Node<T> node = new Node<T>(element,head.getLeft(),head);
head.getLeft().setRight(node);
head.setLeft(node);
return true;
} //首添
public boolean addHead(T element) {
if(element == null) return false;
Node<T> node = new Node<T>(element,head,head.getRight());
head.getRight().setLeft(node);
head.setRight(node);
return false;
} //表index处,添加新数据element
public boolean addByIndex(int index, T element) {
if(index <= 0) {
return addHead(element);
}else if(index >= Length()) {
return add(element);
}else {
int k = 0;
Node<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
Node<T> node = new Node<T>(element,temp.getLeft(),temp);
temp.getLeft().setRight(node);
temp.setLeft(node);
}
return true;
} //将参数中的链表添加到当前链表的尾部
public boolean add(Listable<T> slist) {
if(slist.isEmpty() || slist == null) return false;
if(slist instanceof DoubleLinkedList) {
DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
//以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
for(int i = 0; i < list.Length(); i++) {
temp.add(list.getElement(i));
}
Node<T> node = temp.head;
Node<T> nodeLeft = node.getLeft();
Node<T> nodeRight = node.getRight();
this.head.getLeft().setRight(node.getRight());
nodeRight.setLeft(this.head.getLeft());
nodeLeft.setRight(this.head);
this.head.setLeft(node.getLeft());
return true;
}else {
return false;
}
} //删除下标Index处的数据
public T remove(int index) {
if(isEmpty()) return null;
if(index < 0) {
index = 0;
}
int len = Length();
if(index >= len) {
//当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
index = len-1;
}
T element = null;
if(index >= 0 && index < len) {
Node<T> temp = head;
int k = 0;
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
element = temp.getData();
temp.getRight().setLeft(temp.getLeft());
temp.getLeft().setRight(temp.getRight());
temp.setRight(null);
temp.setLeft(null);
temp = null;
}
return element;
} //删除当前链表中所有的数据,只剩头结点
public boolean removeAll() {
if(isEmpty()) return false;
Node<T> temp = head.getRight();
while(temp != head) {
head.setRight(temp.getRight());
temp.getRight().setLeft(head);
temp.setLeft(null);
temp.setRight(null);
temp = head.getRight();
}
return true;
} //删除链表中从head开始的第一个element数据
public T remove(T element) {
if(isEmpty() || element == null) return null;
//从表中第一个元素开始比较
Node<T> temp = head.getRight();
int k=0;
while(temp != head) {
if(element.equals(temp.getData())) {
remove(k);
return element;
}else {
temp = temp.getRight();
k++;
}
}
if(k == (Length()-1)) {
System.out.println("该链表中没有该数据");
}
return element;
} //修改下标index处的数据,并将原始数据返回
public T setElement(int index,T element) {
if(index < 0 || index >= Length()) return null;
Node<T> temp = head;
int k = 0;
while(k < index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
T tempEle = temp.getData();
temp.setData(element);
return tempEle;
} //重写父类toString方法,实际是给list做遍历后将数据打印出来
public String toString() {
StringBuffer sb = new StringBuffer();
/*通过for循环遍历双向循环链表
int length = Length();
sb.append("[ ");
for(int i = 0; i < length; i++) {
sb.append(getElement(i)+" ");
}
sb.append("]");
*/
//从表头开始遍历双向循环链表
sb.append("[ ");
Node<T> node = head;
while(node.getRight() != head) {
sb.append(node.getRight().getData()+" ");
node = node.getRight();
}
sb.append("]");
return sb.toString();
} }

测试类

 package list;

 //************************************************
//*双向循环链表-java实现(画图分析会容易理解得多)
//************************************************ public class TestDoubleLinkedList {
public static void main(String[] args) {
Listable<String> list = new DoubleLinkedList<String>("a");
list.add("b");
list.add("c");
list.addByIndex(3,"e");
list.addByIndex(3,"d");
list.addByIndex(5,"f");
System.out.println(list);
list.addHead("A");
System.out.println(list.Length());
System.out.println(list);
Listable<String> list1 = new DoubleLinkedList<String>("123456");
list.add(list1);
System.out.println(list);
list.remove(100);
list.add("123456");
System.out.println("list="+list);
System.out.println(list1);
list1.removeAll();
System.out.println(list1+" list1 is Empty??"+list1.isEmpty());
list.remove("123456");
System.out.println("list="+list);
System.out.println("remove item="+list.remove("A"));
System.out.println("list="+list);
}
}

完整代码

 package list;

 //************************************************
//*双向循环链表-java实现(画图分析会容易理解得多)
//************************************************ public class TestDoubleLinkedList {
public static void main(String[] args) {
Listable<String> list = new DoubleLinkedList<String>("a");
list.add("b");
list.add("c");
list.addByIndex(3,"e");
list.addByIndex(3,"d");
list.addByIndex(5,"f");
System.out.println(list);
list.addHead("A");
System.out.println(list.Length());
System.out.println(list);
Listable<String> list1 = new DoubleLinkedList<String>("123456");
list.add(list1);
System.out.println(list);
list.remove(100);
list.add("123456");
System.out.println("list="+list);
System.out.println(list1);
list1.removeAll();
System.out.println(list1+" list1 is Empty??"+list1.isEmpty());
list.remove("123456");
System.out.println("list="+list);
System.out.println("remove item="+list.remove("A"));
System.out.println("list="+list);
}
} //结点类
class Node<T> {
private Node<T> left,right;
private T data; Node(T data) {
this(data,null,null);
} Node() {
this(null,null,null);
} Node(T data,Node<T> left,Node<T> right) {
this.data = data;
this.left = left;
this.right = right;
} public T getData() {
return this.data;
} public Node<T> getLeft() {
return this.left;
} public Node<T> getRight() {
return this.right;
} public void setData(T data) {
this.data = data;
} public void setRight(Node<T> right) {
this.right = right;
} public void setLeft(Node<T> left) {
this.left = left;
} public String toString() {
return getData().toString();
}
} //接口实现类
class DoubleLinkedList<T> implements Listable<T> {
public Node<T> head; //建空表,带头结点
DoubleLinkedList() {
this(null);
} //建表,带头结点,表中有一条数据元素
DoubleLinkedList(T element) {
if(element == null) {
head = new Node<T>(element,null,null);
head.setRight(head);
head.setLeft(head);
}else {
Node<T> headRight = new Node<T>(element,null,null);
head = new Node<T>(null,headRight,headRight);
headRight.setLeft(head);
headRight.setRight(head);
}
} //清空当前链表
public void clear() {} //判空表
public boolean isEmpty() {
return head.getRight() == head;
} //表长
public int Length() {
int len = 0;
Node<T> temp = head;
while(temp.getRight() != head) {
len++;
temp = temp.getRight();
}
return len;
} //取下标index处的数据
public T getElement(int index) {
if(index <= 0) {
return head.getRight().getData();
}
int len = Length();
if(index >= len) {
return head.getLeft().getData();
}
T element = null;
if(index > 0 && index < len) {
int k = 0;
Node<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
element = temp.getData();
}
return element;
} //尾添
public boolean add(T element) {
if(element == null) return false;
Node<T> node = new Node<T>(element,head.getLeft(),head);
head.getLeft().setRight(node);
head.setLeft(node);
return true;
} //首添
public boolean addHead(T element) {
if(element == null) return false;
Node<T> node = new Node<T>(element,head,head.getRight());
head.getRight().setLeft(node);
head.setRight(node);
return false;
} //表index处,添加新数据element
public boolean addByIndex(int index, T element) {
if(index <= 0) {
return addHead(element);
}else if(index >= Length()) {
return add(element);
}else {
int k = 0;
Node<T> temp = head;
//此处只能用while不能用if,用错好几次
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
Node<T> node = new Node<T>(element,temp.getLeft(),temp);
temp.getLeft().setRight(node);
temp.setLeft(node);
}
return true;
} //将参数中的链表添加到当前链表的尾部
public boolean add(Listable<T> slist) {
if(slist.isEmpty() || slist == null) return false;
if(slist instanceof DoubleLinkedList) {
DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
//以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
for(int i = 0; i < list.Length(); i++) {
temp.add(list.getElement(i));
}
Node<T> node = temp.head;
Node<T> nodeLeft = node.getLeft();
Node<T> nodeRight = node.getRight();
this.head.getLeft().setRight(node.getRight());
nodeRight.setLeft(this.head.getLeft());
nodeLeft.setRight(this.head);
this.head.setLeft(node.getLeft());
return true;
}else {
return false;
}
} //删除下标Index处的数据
public T remove(int index) {
if(isEmpty()) return null;
if(index < 0) {
index = 0;
}
int len = Length();
if(index >= len) {
//当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
index = len-1;
}
T element = null;
if(index >= 0 && index < len) {
Node<T> temp = head;
int k = 0;
while(k <= index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
element = temp.getData();
temp.getRight().setLeft(temp.getLeft());
temp.getLeft().setRight(temp.getRight());
temp.setRight(null);
temp.setLeft(null);
temp = null;
}
return element;
} //删除当前链表中所有的数据,只剩头结点
public boolean removeAll() {
if(isEmpty()) return false;
Node<T> temp = head.getRight();
while(temp != head) {
head.setRight(temp.getRight());
temp.getRight().setLeft(head);
temp.setLeft(null);
temp.setRight(null);
temp = head.getRight();
}
return true;
} //删除链表中从head开始的第一个element数据
public T remove(T element) {
if(isEmpty() || element == null) return null;
//从表中第一个元素开始比较
Node<T> temp = head.getRight();
int k=0;
while(temp != head) {
if(element.equals(temp.getData())) {
remove(k);
return element;
}else {
temp = temp.getRight();
k++;
}
}
if(k == (Length()-1)) {
System.out.println("该链表中没有该数据");
}
return element;
} //修改下标index处的数据,并将原始数据返回
public T setElement(int index,T element) {
if(index < 0 || index >= Length()) return null;
Node<T> temp = head;
int k = 0;
while(k < index && temp.getRight() != head) {
k++;
temp = temp.getRight();
}
T tempEle = temp.getData();
temp.setData(element);
return tempEle;
} //重写父类toString方法,实际是给list做遍历后将数据打印出来
public String toString() {
StringBuffer sb = new StringBuffer();
/*通过for循环遍历双向循环链表
int length = Length();
sb.append("[ ");
for(int i = 0; i < length; i++) {
sb.append(getElement(i)+" ");
}
sb.append("]");
*/
//从表头开始遍历双向循环链表
sb.append("[ ");
Node<T> node = head;
while(node.getRight() != head) {
sb.append(node.getRight().getData()+" ");
node = node.getRight();
}
sb.append("]");
return sb.toString();
} }

后期会添加两个链表求交集等操作。

java与数据结构(4)---java实现双向循环链表的更多相关文章

  1. java与数据结构(3)---java实现循环链表

    循环链表:将单链表中尾结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种首尾相接的单链表称为单链表循环表,即循环链表. 循环链表与单链表最重要的区别是:尾结点的指针,不再是p->n ...

  2. java与数据结构(8)---java实现链队列

    链队列 实际上就是单链表,只是规定了删除在队头进行,添加在队尾进行. 链队列代码结构 package list.queue; public interface Queuable<T>; p ...

  3. java与数据结构(6)---java实现链栈

    栈之链式存储结构链栈 链栈 栈的链式存储结构成为链栈.链栈是没有头结点,头结点就是栈顶指针top. 代码结构 package list; public interface Stackable;公共接口 ...

  4. java与数据结构(2)---java实现静态链表

    结点类 1 //结点类 2 class Node<T> { 3 private T data; 4 private int cursor; 5 6 Node(T data, int cur ...

  5. java数据结构-06双向循环链表

    双向循环链表跟单向链表一样,都是头尾相连,不过单向是尾指向头,双向是头尾互相指,可以从前往后查,也可以从后往前查 无头结点的双向循环链表 public class CircleLinkedList&l ...

  6. 双向循环链表的Java版本实现

    1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...

  7. java实现双向循环链表

    java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...

  8. (java实现)双向循环链表

    什么是双向循环链表 在了解双向循环链表之前,如果对链表还没有一个清晰的概念,建议你看看单链表和单向循环链表,这有利于你更好的理解下面的内容.(废话有点多[逃] 相比单链表,双向循环链表是一个更加复杂的 ...

  9. 数据结构(java版)学习笔记(四)——线性表之循环链表

    单向循环链表 PS:有阴影的结点是头结点 概念: 最后一个结点的链域值不为NULL,而是指向头结点 特点: 从表中的任意结点出发,都可以找到表中其他结点 循环条件 p==h 双向链表 概念 链表中的每 ...

随机推荐

  1. [Angular 2] Handling Click Events with Subjects

    While Angular 2 usually uses event handlers to manage events and RxJS typically uses Observable.from ...

  2. C++虚函数及虚函数表解析

    一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...

  3. 多表关联查询(ORACLE版)

    前言:这几天学习oracle,把自己对于关联查询的理解,记录下.如有错误请指正! 交叉连接: 交欢连接又称为“笛卡儿积连接”,是两个或多个表之间的无条件连接.一个表中所有的记录与其它表的所有的记录进行 ...

  4. SparseArray HashMap 稀疏数组 二分法

    简介 HashMap是java里比较常用的一个集合类,我们常用其来缓存一些处理后的结果,但是在Android项目中,Eclipse却给出了一个 performance 警告.意思就是说用SparseA ...

  5. css改变滚动条样式

    /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/ ::-webkit-scrollbar { width: 10px; height: 12px; background-color: #F5 ...

  6. JAVAEE学习

    首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA).J2SE,Java 2 Platform Standard Edition,我们经常说到的JDK,就主要指的这个,它 ...

  7. CADisplayLink的简单使用

    CADisplayLink类似NSTimer是一个定时器,只不过是一秒会调用60次指定的方法 使用方法: #import "ViewController.h" @interface ...

  8. JavaScript 客户端JavaScript之 脚本化浏览器窗口

    1.计时器 客户端Javascript以全局函数setTimeOut().clearTimeOut().setInterval().clearInterval()提供这一功能.   前者是从运行的那一 ...

  9. Linq中字段数据类型转换问题(Linq to entity,LINQ to Entities 不识别方法"System.String ToString()"问题解决)

    1.在工作中碰到这样一个问题: 使用linq时,需要查询两个表,在这两张表中关联字段分别是int,和varchar()也就是string,在linq中对这两个字段进行关联, 如果强制类型转换两个不同类 ...

  10. token验证 sae

    在微信平台中修改服务器设置时,使用微信Demo的php,刚开始一直验证token 失败 解决办法 :在echo $echoStr;之前添加header('content-type:text');一句这 ...