之前学习数据结构并没有注意过双链表的问题。现在专门拿出来学习一下。
首先推荐点击打开链接这篇文章。讲得很好,专门以linux内核中的数据结构为例讲述了双向链表在内核中的应用。最主要的还是删除和插入操作,这两个搞明白了基本也差不多了。双链表可以让头尾节点指向对方这样双向链表也就变成了循环链表。相较于单链表来说双向链表的优点是可以很轻易的获得其前节点和后节点。缺点是每个节点需要保存两个指向节点的指针,需要更多的空间开销。我还是不多废话直接贴代码吧。
#ifndef DOUBLE_LIST_H
#define DOUBLE_LIST_H
struct Node;
typedef struct Node * PtrToNode;
typedef PtrToNode DoubleList;//指向头节点
typedef PtrToNode Position;
typedef int ElementType;
PtrToNode Create_DoubleList();
void PrintList(DoubleList L);
void Insert(DoubleList L,ElementType x,Position P);
Position find(DoubleList L,ElementType x);
void Delet(DoubleList L,ElementType x);
struct Node
{
ElementType Element;
Position prev;
Position next;
};
#endif
#include "double.h"
Double_List List_Head;
//创建头节点
PtrToNode Create_DoubleList(Double_List List_Head)
{
List_Head=(Double_List)malloc(sizeof(Node));
if(!List_Head)
{
printf("creat node error");
}
List_Head->next=NULL;
List_Head->prev=NULL;
return List_Head;
}
Position find(DoubleList L,ElementType x)
{
Position p;
p=L-next;
if(p==NULL)
{
printf("the list is empty");
return NULL;
}
while(p!=NULL&&p->Element!=x)
{
p=p->next;
}
return p;
}
void Delet(DoubleList L,ElementType x)
{
Position p;
p=find(L,x);
if(P==NULL)
printf("did not find x");
else{
p->pre->next=p->next;
p->next->pre=p->pre;
free(p);
}
}
//尾插
void Insert(DoubleList L,ElementType x,Position P)
{
Position Temp;
Temp=(Position)malloc(sizeof(Node));
if(Temp==NULL)
printf("out of space!");
Temp->Element=x;
Temp->next=P->next;
if(P->next!=NULL)
P->next->prev=Temp;
Temp->prev=P;
P->next=Temp;
}
//遍历
void PrintList(DoubleList L)
{
PtrToNode p;
p=L->next;
if(p==NULL)
printf("the list is empty");
while(P!=NULL)
{
printf("%d\n",p->Element);
p=p->next;
}
}
双向链表的查找遍历操作和单链表没有太大区别,需要注意的是插入和删除操作需要注意两个指针的操作。链表到这里结束,下一章堆栈。