双向带头单链表:在单链表的每个结点中,在设置一个指向其前驱结点的指针域。因此,在双向链表中的结点有两个指针域,一个指向直接前驱,一个指向直接后继。其存储结构定义如下:
typedef int DataType;
typedef struct DoublieList
{
DataType data;
struct DoublieList *pre; //指向直接前驱
struct DoublieList *next; //指向直接后继
}DoubleList;
下面介绍一下其相关的操作
初始化操作:双向带头单链表需要一个头结点,因此在初始化的时候,需要创建一个头结点。
void InitDoubleList(DoubleList **pHead)
{
DoubleList *newNode = (DoubleList *)malloc(sizeof(DoubleList));
assert(newNode);
newNode->pre = newNode->next = newNode;
*pHead = newNode;
}
清空操作:
void ClearDoubleList(DoubleList *pHead)
{
DoubleList *cur = pHead->next;
DoubleList *next;
for(cur=pHead; cur!= NULL; cur=next)
{
next = cur->next;
free(cur);
}
pHead->pre = pHead;
pHead->next = pHead;
}
销毁操作:
void DestroyDoubleList(DoubleList **pHead)
{
ClearDoubleList(*pHead);
free(*pHead);
*pHead = NULL;
}
这两个操作有一些不同:清空是将该链表中的数据信息清空,但是仍然保留了头结点
而销毁操作不仅是将数据信息清空,而且还将头结点释放。
插入操作:
在pos位置处插入一个新的节点。插入操作的顺序可看作先搞定新结点的前驱和后继,然后搞定后结点的前驱,最后解决前结点的后继。示意图如下:
void InsertDoubleList(DoubleList *pHead, DoubleList* pos, int data)
{
DoubleList *newNode = (DoubleList *)malloc(sizeof(DoubleList));
newNode->data = data;
newNode->pre = pos->pre;
newNode->next = pos;
pos->next->pre = newNode;
pos->pre = newNode;
}
删除操作:
删除pos位置处的结点,只需要以下两步:如图
void DeleteDoubleList(DoubleList *pHead, DoubleList* pos)
{
assert(pos != pHead);
pos->pre->next = pos->next;
pos->next->pre = pos->pre;
free(pos);
}