一、什么是双向循环链表?
-
双向链表是每个结点除后继指针外还有一个前驱指针。和单链表类同,双向链表也有带头结点结构和不带头结点结构两种,带头结点的双向链表更为常用;另外,双向链表也可以有循环和非循环两种结构,循环结构的双向链表更为常用。
-
在双向链表中,每个结点包括三个域,分别是element域、next域和prior域,其中element域为数据元素域,next域为指向后继结点的对象引用,prior域为指向前驱结点的对象引用。
如下图是带头结点的循环双向链表的图示结构。循环双向链表的next和prior各自构成自己的循环单链表。
二、带头结点的双向循环链表的实现
1、接口的定义:
interface IList1{ //线性表的抽象数据Java接口
public void clear();
public boolean isEmpty();
public int length();
public Object get(int i) throws Exception;
public void insert(int i, Object x) throws Exception;
public void remove(int i) throws Exception;
public int indexOf(Object x);
public void display();
}
2、结点的定义:
class DuLNode{
public Object data;
public DuLNode prior;
public DuLNode next;
public DuLNode() {
this(null);
}
public DuLNode(Object data) {
this.data = data;
this.prior = null;
this.next = null;
}
}
3、构造带头结点的双向循环链表:
class DuLinkList implements IList1{
public DuLNode head;
public DuLinkList() {
head = new DuLNode();
head.prior = head;
head.next = head;
}
}
4、插入元素:
public void insert(int i, Object x) throws Exception {
// TODO Auto-generated method stub
DuLNode p = head.next;
int j = 0;
while(!p.equals(head) && j<i) {
p = p.next;
++j;
}
if(j!=i && !p.equals(head))
throw new Exception("插入位置不合法");
DuLNode s = new DuLNode(x);
p.prior.next = s;
s.prior = p.prior;
s.next = p;
p.prior = s;
}
5、用头插法创建带头结点双向循环链表:
public DuLinkList(int n) throws Exception{
this();
Scanner sc = new Scanner(System.in);
for(int j=0; j<n; j++)
insert(0,sc.next());
}
6、清空双向循环链表:
public void clear() {
head.data = null;
head.next = null;
}
7、判断双向循环链表是否为空:
public boolean isEmpty() {
return head.next == null;
}
8、返回双向循环链表的长度:
public int length() {
DuLNode p = head;
int len = 0;
while(p.next!= head) {
p = p.next;
++len;
}
return len;
}
10、返回指定位置的元素:
public Object get(int i) throws Exception {
DuLNode p = head.next;
int j = 0;
while(p != null && j<i) {
p = p.next;
++j;
}
if(j>i || p == null) {
throw new Exception("第" + i + "个元素不存在");
}
return p.data;
}
11、删除指定位置的元素:
public void remove(int i) throws Exception {
DuLNode p = head.next;
int j = 0;
while(!p.equals(head) && j<i) {
p = p.next;
++j;
}
if(j!=i)
throw new Exception("删除位置不合理");
p.prior.next = p.next;
p.next.prior = p.prior;
}
12、返回指定元素的位置:
public int indexOf(Object x) {
DuLNode p = head;
int j=0;
while(p.next!=head) {
if(p.next.data.equals(x))
break;
p = p.next;
++j;
}
if(p.next != head)
return j;
else
return -1;
}
13、遍历输出元素:
public void display() {
DuLNode node = head.next;
while(!node.equals(head)) {
System.out.print(node.data + "");
node = node .next;
}
System.out.println();
}
附上全部代码:
import java.util.Scanner;
interface IList1{ //线性表的抽象数据Java接口
public void clear();
public boolean isEmpty();
public int length();
public Object get(int i) throws Exception;
public void insert(int i, Object x) throws Exception;
public void remove(int i) throws Exception;
public int indexOf(Object x);
public void display();
}
class DuLNode{
public Object data;
public DuLNode prior;
public DuLNode next;
public DuLNode() {
this(null);
}
public DuLNode(Object data) {
this.data = data;
this.prior = null;
this.next = null;
}
}
class DuLinkList implements IList1{
public DuLNode head;
public DuLinkList() {
head = new DuLNode();
head.prior = head;
head.next = head;
}
public DuLinkList(int n) throws Exception{
this();
Scanner sc = new Scanner(System.in);
for(int j=0; j<n; j++)
insert(0,sc.next());
}
public void clear() {
// TODO Auto-generated method stub
head.data = null;
head.next = null;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
return head.next == null;
}
public int length() {
// TODO Auto-generated method stub
DuLNode p = head;
int len = 0;
while(p.next!= head) {
p = p.next;
++len;
}
return len;
}
public Object get(int i) throws Exception {
// TODO Auto-generated method stub
DuLNode p = head.next;
int j = 0;
while(p != null && j<i) {
p = p.next;
++j;
}
if(j>i || p == null) {
throw new Exception("第" + i + "个元素不存在");
}
return p.data;
}
public void insert(int i, Object x) throws Exception {
// TODO Auto-generated method stub
DuLNode p = head.next;
int j = 0;
while(!p.equals(head) && j<i) {
p = p.next;
++j;
}
if(j!=i && !p.equals(head))
throw new Exception("插入位置不合法");
DuLNode s = new DuLNode(x);
p.prior.next = s;
s.prior = p.prior;
s.next = p;
p.prior = s;
}
public void remove(int i) throws Exception {
// TODO Auto-generated method stub
DuLNode p = head.next;
int j = 0;
while(!p.equals(head) && j<i) {
p = p.next;
++j;
}
if(j!=i)
throw new Exception("删除位置不合理");
p.prior.next = p.next;
p.next.prior = p.prior;
}
public int indexOf(Object x) {
DuLNode p = head;
int j=0;
while(p.next!=head) {
if(p.next.data.equals(x))
break;
p = p.next;
++j;
}
if(p.next != head)
return j;
else
return -1;
}
public void display() {
// TODO Auto-generated method stub
DuLNode node = head.next;
while(!node.equals(head)) {
System.out.print(node.data + "");
node = node .next;
}
System.out.println();
}
}
public class Task_7_2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
System.out.print("输入双向循环链表的长度:");
int n = cin.nextInt();
DuLinkList L = new DuLinkList();
System.out.print("用头插法依次输入双向循环链表的值:");
for(int i=0; i<n; i++)
L.insert(0, cin.nextInt());
System.out.print("此时双向循环链表各元素的值:");
L.display();
L.insert(3,3);
System.out.print("插入元素'3'后的双向循环链表:");
L.display();
System.out.println("此时双向循环链表的长度:" + L.length());
L.remove(6);
System.out.print("删除位置'6'后的双向循环链表:");
L.display();
System.out.print("输入要查找的位置:");
int m = cin.nextInt();
if(m>L.length() || L.get(m)==null)
System.out.println("该元素不存在!");
else
System.out.println("查找的位置上的值:" + L.get(m));
System.out.print("输入要查找的值:");
int k = L.indexOf(cin.nextInt());
if(k!=-1)
System.out.println("查找的值所在的位置:" + k);
else
System.out.println("该元素不存在!");
}
}
运行结果: