双向链表是在单链表的基础上为每个结点添加一个前趋指针域prior,这样形成的链表可有两个不同的方向。
双向链表一般也可由头指针唯一确定,其每一结点均有:
数据域(data)
左链域(prior):指向前趋结点.
右链域(next):指向后继
它是一种既有前趋也有后继的对称结构,它的对称性可表述为:
p->prior->next=p->next->prior=p
即:结点*p的存储位置,既存放在其前趋结点(*p->prior)的后继指针域中;也存放在其后继结点(*p->next)的前趋指针域中。
双向链表的示意图如下:
同单链表相比,双向链表的插入、删除和查找的操作都更为便利。
0.双向链表的结点类型
typedef struct DNode
{
int data;
DNode *prior;
DNode *next;
}DLNode;
1.初始化双向链表
/*初始化链表,该链表含有一个为空的头结点,该节点的next指针和prior指针都指向自身*/
void ListInitiate(DLNode **head)
{
*head=new DLNode;
(*head)->next=*head;
(*head)->prior=*head;
}
初始化的双向链表其结构大致如下:
2.创建双向链表
/*创建含(n-m+1)个元结点的链表,每个结点数据域中的值为i(m≤i≤n)*/
void ListCreate(DLNode *head,int m,int n)
{
DLNode *p,*q;
p=head;
int i;
for(i=m;i<=n;i++)
{
q=new DLNode; //新建一个结点
q->data=i; //为结点的数据域赋值
q->prior=p; //①
q->next=p->next; //②
p->next->prior=q; //③
p->next=q; //④
p=q;
}
}
注意代码中的①②③④语句所建立的前趋或后继的指向与图3中的①②③④箭头对应。
3.查找值为x的结点*p
/*查找数据域值为x的指针p;
该函数返回的是一个指针,该指针指向DLNode类型数据*/
DLNode *ListGet(DLNode *head,int x)
{
DLNode *p;
p=head->next;
while(p!=head)
{
if(p->data!=x)
p=p->next;
else
return(p);
}
return NULL;
}
4.插入新结点
在步骤3中找到的*p结点之前插入一个新结点
/*在结点*p之前插入值为x的新结点*/
void ListInsert(DLNode *p,int x)
{
DLNode *q;
q=new DLNode;
q->data=x;
p->prior->next=q;
q->prior=p->prior;
p->prior=q;
q->next=p;
}
5.删除结点*p
/*删除链表中的*p结点*/
void ListDelete(DLNode *p)
{
DLNode *q;
p->next->prior=p->prior;
p->prior->next=p->next;
q=p;
delete q;
}
6.打印链表中的元素
/*打印链表中的元素*/
void ListPrint(DLNode *head)
{
DLNode *p;
p=head;
while(p->next!=head){
p=p->next;
cout<<p->data<<' ';
}
cout<<endl;
}
完整的代码如下:
#include <iostream>
using namespace std;
typedef struct DNode
{
int data;
DNode *prior;
DNode *next;
}DLNode;
int main()
{
void ListInitiate(DLNode **head);
void ListCreate(DLNode *head,int m,int n);
DLNode *ListGet(DLNode *head,int x);
void ListInsert(DLNode *p,int x);
void ListDelete(DLNode *p);
void ListPrint(DLNode *head);
DLNode *head,*p;
ListInitiate(&head);
ListCreate(head,1,10); //创建一个链表,链表中元素值在1~10之间
p=ListGet(head,5); //返回元素值为5的结点(p)的地址,
ListInsert(p,99); //在结点p之前插入一个元素值为99的新结点
ListDelete(p); //删除p结点
ListPrint(head); //打印链表中的元素
return 0;
}
/*初始化链表,该链表含有一个为空的头结点,该节点的next指针和prior指针都指向自身*/
void ListInitiate(DLNode **head)
{
*head=new DLNode;
(*head)->next=*head;
(*head)->prior=*head;
}
/*创建含(n-m+1)个元结点的链表,每个结点数据域中的值为i(m≤i≤n)*/
void ListCreate(DLNode *head,int m,int n)
{
DLNode *p,*q;
p=head;
int i;
for(i=m;i<=n;i++)
{
q=new DLNode;
q->data=i;
q->prior=p; //①
q->next=p->next; //②
p->next->prior=q; //③
p->next=q; //④
p=q;
}
}
/*查找数据域值为x的指针p;
该函数返回的是一个指针,该指针指向DLNode类型数据*/
DLNode *ListGet(DLNode *head,int x)
{
DLNode *p;
p=head->next;
while(p!=head)
{
if(p->data!=x)
p=p->next;
else
return(p);
}
return NULL;
}
/*在结点*p之前插入值为x的新结点*/
void ListInsert(DLNode *p,int x)
{
DLNode *q;
q=new DLNode;
q->data=x;
p->prior->next=q;
q->prior=p->prior;
p->prior=q;
q->next=p;
}
/*删除链表中的*p结点*/
void ListDelete(DLNode *p)
{
DLNode *q;
p->next->prior=p->prior;
p->prior->next=p->next;
q=p;
delete q;
}
/*打印链表中的元素*/
void ListPrint(DLNode *head)
{
DLNode *p;
p=head;
while(p->next!=head){
p=p->next;
cout<<p->data<<' ';
}
cout<<endl;
}