1.前言:
在前面介绍的单链表时候,我们了解到它的指针域只包含了一个指向后继结点的指针,这会造成它无法逆向检索,因此我们引入双链表,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。
2.双链表的相关操作
2.1 建立存储结构
//存储结构
typedef struct DNode
{
Elemtype data;
struct DNode *prior;
struct DNode *next;
}DNLinkNode,*DLinklist;//DLinklist等价于*DNode
2.2 初始化
这里我们定义带头结点的双链表,那么具体的建立操作就是先建立头节点,让其后继指针指向NULL,其前继指针永远指向NULL。
//初始化
bool InitDLinkList(DLinklist & L)
{
L=(DNode *)malloc(sizeof(DNode));//分配一个头节点
if(L==NULL) //内存不够分配失败
return false;
L->prior=NULL;//头节点prior永远指向NULL
L->next=NULL;//头节点后还没有结点
return true;
}
2.3 插入与删除
这两项操作是最不同于单链表的,也是相对麻烦的操作,下面先通过示意图理解其过程。
了解原理后便可以在表的指定位置插入元素,代码如下:
//插入元素
bool InserSqList(DLinklist &L,int i,Elemtype e)
{
int j=0;
DNLinkNode *p=L,*s;
if(i<=0) return false;
while(j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
s=(DNLinkNode *)malloc(sizeof(DNLinkNode));
s->data=e;
s->next=p->next;
if(p->next!=NULL)
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
}
同样的了解完删除节点原理, 我们就可以删除链表中指定位置的元素。
//删除元素
bool DeleteSqlist(DNode *& L,int i)
{
int j;
DNode *p=L,*q;
if(i<0) return false;
while (j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
q=p->next;
if(q==NULL)
return false;
p->next=q->next;
if(q->next!=NULL)
q->next->prior=p;
free(q);
return true;
}
}
2.4 输出表
这一操作相对就简单许多。
void display(DNode *L)
{
DNode *p=L->next;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
printf("\n");
}
}
全部代码:
#include<stdio.h>
#include<malloc.h>
typedef int Elemtype;
//存储结构
typedef struct DNode
{
Elemtype data;
struct DNode *prior;
struct DNode *next;
}DNLinkNode,*DLinklist;//DLinklist等价于*DNode
//初始化
bool InitDLinkList(DLinklist & L)
{
L=(DNode *)malloc(sizeof(DNode));//分配一个头节点
if(L==NULL) //内存不够分配失败
return false;
L->prior=NULL;//头节点prior永远指向NULL
L->next=NULL;//头节点后还没有结点
return true;
}
//插入元素
bool InserSqList(DLinklist &L,int i,Elemtype e)
{
int j=0;
DNLinkNode *p=L,*s;
if(i<=0) return false;
while(j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
s=(DNLinkNode *)malloc(sizeof(DNLinkNode));
s->data=e;
s->next=p->next;
if(p->next!=NULL)
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
}
//删除指定位置元素
bool DeleteSqlist(DNode *& L,int i)
{
int j;
DNode *p=L,*q;
if(i<0) return false;
while (j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
q=p->next;
if(q==NULL)
return false;
p->next=q->next;
if(q->next!=NULL)
q->next->prior=p;
free(q);
return true;
}
}
//后向便历遍历
void display(DNode *L)
{
DNode *p=L->next;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
printf("\n");
}
}
//删除结点
bool DeleteNextDNode(DNode *p)
{
if(p==NULL) return false;
DNode *q=p->next;//找到p的后继结点q
if(q==NULL) return false;
p->next=q->next;
if(q->next!=NULL)//q结点不是最后一个结点
q->next->prior=p;
free(q);
return true;
}
//销毁表
void DestoryList(DNode *&L)
{
while (L->next!=NULL)
DeleteNextDNode(L);
free(L);//释放头节点
L=NULL;//头节点指向NULL
}
int main()
{
DLinklist L;
InitDLinkList(L);
InserSqList(L,1,1);
InserSqList(L,2,3);
InserSqList(L,3,4);
InserSqList(L,4,5);
display(L);
DeleteSqlist(L,1);
display(L);
DestoryList(L);
return 0;
}
结果如图:
不足之处还请多多指教。