文章目录
定义
双向链表( double linked list )由单链表演化而来,在单链表的每个节点中,在设置一个指向其前驱节点的指针域。
实际含义:
我们不仅需要正向的循环播放,亦需要反向循环功能。
例如监控探头的倒带功能,以及很多设计软件的回溯功能。
代码实现( Java )
Java 语言
package com.example;
/*
* 对比单向链表:需要插入一个节点的前驱指针
* 改变了插入,删除的方法
* 整体:用空间来换时间的操作
*/
public class DupleLoopLinkList<T> {
@SuppressWarnings("hiding")
class Node<T> {
protected Node<T> next;
protected Node<T> prior;
protected T data;
public Node(T data){
this.data = data;
}
}
/* 产生头结点 */
public Node<T> head;
/*线性表长度 */
private int size;
/* 初始化顺序线性表 */
void initList(DupleLoopLinkList<T> list){
list.head = new Node<T>(null);
list.head.next=list.head;
list.head.prior=list.head;
list.size = 0;
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
boolean listEmpty(DupleLoopLinkList<T> list){
if(list.size==0)
return true;
else
return false;
}
//真正置空的模式儿
int clearListAll(DupleLoopLinkList<T> list){
Node<T> tempNode = head;
while(tempNode != null){
Node<T> replace = tempNode.next;
tempNode.data = null;
tempNode.next = null;
tempNode.prior = null;
tempNode = replace;
}
tempNode = null;
size = 0;
//重新初始化
initList(list);
return 1;
}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
int clearList(DupleLoopLinkList<T> list){
//无法做到像C语言中的free(),直接放到内存空间
list = new DupleLoopLinkList<T>();
return 1;
}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int listLength(DupleLoopLinkList<T> list){
int i =0;
Node<T> tempNode = list.head;
while(tempNode.next != list.head){
tempNode=tempNode.next;
i++;
}
return i;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
T getElem(DupleLoopLinkList<T> list, int index){
T data;
int position = 0;
Node<T> current = head;
if(index>=0 && index<size){
while(position != index){
current = current.next;
position++;
}
data = (T)current.data;
}else{
throw new IndexOutOfBoundsException("超出链表长度");
}
return data;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int locateElem(DupleLoopLinkList<T> list, T e){
int temp =0;
Node<T> tempNode = head;
while(e != tempNode.data && temp < size-1){
tempNode = tempNode.next;
temp++;
}
if(e == tempNode.data){
return temp;
}else{
System.out.println("未找到!");
return -1;
}
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
/* 插入逻辑:当插入的位置已有元素时,原元素退后一格,没有时,开辟新空间放置新元素*/
int listInsert(DupleLoopLinkList<T> list, int index, T elem){
Node<T> preNode = head;
int position = 2;
if(index<0 || index > size+1){
throw new IndexOutOfBoundsException("index 位置不合法");
}else if(index ==1){
if(head.data ==null){
head.data=elem;
size++;
}else{
addFromHead(elem);
}
}else if(list.size ==1){
Node<T> newNode = new Node<T>(elem);
head.next=newNode;
head.prior=newNode;
newNode.next=head;
newNode.prior=head;
size++;
}else if(index == this.size+1){
addFromTail(elem);
}else{
while(position != index ){
preNode = preNode.next;
position++;
}
Node<T> newNode = new Node<T>(elem);
newNode.prior=preNode;
newNode.next=preNode.next;
preNode.next.prior=newNode;
preNode.next=newNode;
size++;
}
return 1;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
public void listDelete(DupleLoopLinkList<T> list,int index){
int position = 0;
Node<T> preNode = list.head;
if(index<0 || index > list.size+1){
throw new IndexOutOfBoundsException("超出链表长度");
}else{
while(position != index-1){
preNode = preNode.next;
position++;
}
preNode.next=preNode.next.next;
preNode.next.prior=preNode;
}
list.size--;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
void listTraverse(DupleLoopLinkList<T> list){
int position = 0;
Node<T> tempNode = head;
while(position != size){
System.out.println(tempNode.data);
tempNode = tempNode.next;
position++;
}
}
//(尾插法)
public void addFromTail(T data){
Node<T> newNode = new Node<T>(data);
newNode.next=head;
newNode.prior=head.prior;
head.prior.next=newNode;
head.prior=newNode;
size++;
}
//(头插法)
public void addFromHead(T data){
Node<T> newNode = new Node<T>(data);
newNode.next=head;
newNode.prior=head.prior;
head.prior.next=newNode;
head=newNode;
size++;
}
public static int clearList3(DupleLoopLinkList<Integer> l){
//无法做到像C语言中的free(),直接放到内存空间
l = new DupleLoopLinkList<Integer>();
return 1;
}
public static void main(String[] args){
DupleLoopLinkList<Integer> L = new DupleLoopLinkList<Integer>();
Integer e;
int j,k;
L.initList(L);
System.out.println("初始化L后:ListLength(L)=%d\n"+L.listLength(L));
for(j=1;j<=5;j++)
L.listInsert(L,j,j);
System.out.println("在L的表头依次插入1~5后:L.data=");
L.listTraverse(L);
System.out.println("ListLength(L)=%d \n"+L.listLength(L));
System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty(L));
L.clearListAll(L);
/*L=L.clearList2(L);*/
System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty(L));
System.out.println("清空L后:ListLength(L)=%d\n"+L.listLength(L));
for(j=1;j<=10;j++)
L.listInsert(L,j,j);
System.out.println("在L的表尾依次插入1~10后:L.data=");
L.listTraverse(L);
System.out.println("ListLength(L)=%d \n"+L.listLength(L));
L.listInsert(L,1,0);
System.out.println("在L的表头插入0后:L.data=");
L.listTraverse(L);
System.out.println("ListLength(L)=%d \n"+L.listLength(L));
e = L.getElem(L,5);
System.out.println("第5个元素的值为:%d\n"+e);
for(j=3;j<=4;j++)
{
k=L.locateElem(L,j);
System.out.println("第%d个元素的值为%d\n"+k);
}
k=L.listLength(L); /* k为表长 */
for(j=k;j>=k;j--)
{
//在删除元素时,需要判断链表长度
System.out.println("正在删除第:"+k);
L.listDelete(L,j); /* 删除第j个数据 */
}
System.out.println("依次输出L的元素:");
L.listTraverse(L);
j=5;
L.listDelete(L,j); /* 删除第5个数据 */
System.out.println("删除第%d个的元素值为:%d\n"+j+e);
System.out.println("依次输出L的元素:");
L.listTraverse(L);
}
}