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

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

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

接口类

 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. setTimeout()的返回值

    今天遇到一个问题,题目如下: var len=4; while(len--){ setTimeout(function(){ console.log(len); },0); console.log(l ...

  2. HDU1159 && POJ1458:Common Subsequence(LCS)

    Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...

  3. 判断直线与线段相交 POJ 3304 Segments

    题意:在二维平面中,给定一些线段,然后判断在某直线上的投影是否有公共点. 转化,既然是投影,那么就是求是否存在一条直线L和所有的线段都相交. 证明: 下面给出具体的分析:先考虑一个特殊的情况,即n=1 ...

  4. printf用法之打印2进制,八进制,十进制,十六进制

    printf是格式化输出函数,它可以直接打印十进制,八进制,十六进制,输出控制符分别为%d, %o, %x, 但是它不存在二进制,如果输出二进制,可以手写,但是也可以调用stdlib.h里面的itoa ...

  5. codesmith的使用

    新建一个C#模版. model类的模版代码如下: <%-- Name: 模型层代码生成模版 Author: XX Description: 根据数据库的内容生成模型层代码 Version: V1 ...

  6. css空格和去浮动的应用

    今天做了项目用到css,请教前端解决,第一个是记得css空格之间的关系是隶属关系,但是在元素中却是并列关系,如<div class="right_side_item_moban gra ...

  7. 武汉科技大学ACM :1001: A+B for Input-Output Practice (I)

    Problem Description Your task is to Calculate a + b. Too easy?! Of course! I specially designed the ...

  8. PHP防止SQL注入的方法

    [一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最 ...

  9. JS判断字符串是否为空、过滤空格、查找字符串位置等函数集

    这是一个由网上收集的JS代码段,用于判断指定字符串是否为空,过滤字符串中某字符两边的空格.查找指定字符串开始的位置.使用IsFloat函数判断一 个字符串是否由数字(int or long or fl ...

  10. Spark运行问题备忘一(网络搜集)

    问题一 ERROR storage.DiskBlockObjectWriter: Uncaught exception -9ca8//shuffle_1_1562_27 java.io.FileNot ...