java与数据结构(4)---java实现双向循环链表
线性表之链式存储结构双向循环链表
双向循环链表:每个结点包含了数据、直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环。可以形象的理解成一群孩子手拉手牵成一个圆圈,从头一个孩子开始可以从左往右报数,也可以从右往左开始报数。
优点:双向循环链表可以迅速的获取当前数据的前驱数据,解决了单向循环链表从头开始遍历的麻烦。
接口类
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实现双向循环链表的更多相关文章
- java与数据结构(3)---java实现循环链表
循环链表:将单链表中尾结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种首尾相接的单链表称为单链表循环表,即循环链表. 循环链表与单链表最重要的区别是:尾结点的指针,不再是p->n ...
- java与数据结构(8)---java实现链队列
链队列 实际上就是单链表,只是规定了删除在队头进行,添加在队尾进行. 链队列代码结构 package list.queue; public interface Queuable<T>; p ...
- java与数据结构(6)---java实现链栈
栈之链式存储结构链栈 链栈 栈的链式存储结构成为链栈.链栈是没有头结点,头结点就是栈顶指针top. 代码结构 package list; public interface Stackable;公共接口 ...
- java与数据结构(2)---java实现静态链表
结点类 1 //结点类 2 class Node<T> { 3 private T data; 4 private int cursor; 5 6 Node(T data, int cur ...
- java数据结构-06双向循环链表
双向循环链表跟单向链表一样,都是头尾相连,不过单向是尾指向头,双向是头尾互相指,可以从前往后查,也可以从后往前查 无头结点的双向循环链表 public class CircleLinkedList&l ...
- 双向循环链表的Java版本实现
1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...
- java实现双向循环链表
java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...
- (java实现)双向循环链表
什么是双向循环链表 在了解双向循环链表之前,如果对链表还没有一个清晰的概念,建议你看看单链表和单向循环链表,这有利于你更好的理解下面的内容.(废话有点多[逃] 相比单链表,双向循环链表是一个更加复杂的 ...
- 数据结构(java版)学习笔记(四)——线性表之循环链表
单向循环链表 PS:有阴影的结点是头结点 概念: 最后一个结点的链域值不为NULL,而是指向头结点 特点: 从表中的任意结点出发,都可以找到表中其他结点 循环条件 p==h 双向链表 概念 链表中的每 ...
随机推荐
- [ES6] Converting an array-like object into an Array with Array.from()
Array.from() lets you convert an "iterable" object (AKA an array-like object) to an array. ...
- codevs 2800 送外卖(状压dp)
/* f[i][j] 表示走过的点构成i状态 且最后到达的点为j时的最优解 在那最后一个状态就是(1<<n+1)-1 每个点都到达 在由此回到0 */ #include<iostre ...
- 兼容IE与firefox火狐的回车事件(js与jquery)
javascript 兼容IE与firefox火狐的回车事件 复制代码代码如下: <script language="javascript"> function key ...
- 关于oracle dblink的知识。
create database link WZGLconnect to MMCSG_GX(用户名)using '(description=(address_list=(address=(host=xx ...
- dom方法读取xml(不常用)
Book.java package com.xml.demo; public class Book { private int id; private String name; private Flo ...
- stax解析XML-----Demo
Demo public void staxDemo() throws Exception { XMLStreamReader xml= XMLInputFactory.newInstance().cr ...
- php 操作xml文件
读取xml:$doc=new DOMDocument(); $doc->load('news.xml'); $news=$doc->getElementsByTagName("n ...
- php 用post请求调用接口api
$post_data=""; $ch = curl_init(); $url = ''; curl_setopt($ch , CURLOPT_URL , $url); curl_s ...
- Nginx源码研究三:Epoll在NGINX中的使用
Web服务器在面对高并发的情况下,网络的IO一般选择IO复用,像apache选择的Select/poll.Nginx在linux 2.6后选择Epoll做网路IO,提高了WEB服务的并发能力. 在本章 ...
- 一元多项式Polynomial的C语言实现
/* 编译器:Dev-c++ 5.4.0 文件名:Polynomial.cpp 代码版本号:1.0 时间:2015年10月9日21:53:26 */ /* 总结: 1.结构体指针指向的区域要手动分配内 ...