结构:图解
循环双链表有两个指针域,分别指向前驱和后继节点,尾结点后继指针指向头节点,头节点的前驱指针指向尾结点,形成一个环。
结构设计:
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define ERROR -1
typedef int ElemType;
typedef struct DuLNode
{
struct DuLNode* prev;
struct DuLNode* next;
ElemType data;
}DuLNode, * PDuLNode; //节点类型
typedef struct
{
DuLNode* head; // 头节点
int cursize;
}DuLinkList; //双链表类型
1.节点申请空间函数
DuLNode* Buynode(ElemType val, DuLNode* parg, DuLNode* narg )
{
DuLNode* s = (DuLNode*)malloc(sizeof(DuLNode));
if (nullptr == s)
{
exit(ERROR);
}
s->prev = (parg == nullptr) ? s : parg; //前驱为空指针,则指向自身
s->next = (narg == nullptr) ? s : narg; //前驱为空指针,则指向自身
s->data = val;
return s;
}
2.初始化函数(创造空链表)
void InitList(DuLinkList* plist)
{
assert(plist != nullptr);
plist->cursize = 0;
plist->head = Buynode(0,nullptr,nullptr); // head node
}
3.释放节点函数
void Freenode(DuLNode* q)
{
free(q);
q = nullptr;
}
4.返回数据节点个数 函数
int GetSize(DuLinkList* plist)
{
assert(plist != nullptr);
return plist->cursize;
}
5.判空函数
bool IsEmpty(DuLinkList* plist)
{
assert(plist != nullptr);
return GetSize(plist) == 0;
}
6.在指定节点前插入数据节点函数
图解原理:
void InsertPrev(DuLinkList* plist, DuLNode* ptr, ElemType val)
{
assert(plist != nullptr && ptr != nullptr);
ptr->prev = Buynode(val, ptr->prev, ptr);
DuLNode* s = ptr->prev;
s->prev->next = s;
plist->cursize += 1;
}
7.头插函数
void Push_front(DuLinkList* plist, ElemType val)
{
assert(plist != nullptr);
InsertPrev(plist, plist->head->next, val); //代码复用
}
8.尾插函数
void Push_back(DuLinkList* plist, ElemType val)
{
assert(plist != nullptr);
InsertPrev(plist, plist->head, val); //代码复用
}
9.查找指定数据的节点 函数
DuLNode* FindValue(DuLinkList* plist, ElemType val)
{
assert(plist != nullptr);
DuLNode* p = plist->head->next;
while (p != plist->head && p->data != val)
{
p = p->next;
}
if (p == plist->head)
{
p = nullptr; //无满足要求的节点,返回空指针
}
return p;
}
10.删除指定节点
图解原理:
void Erase(DuLinkList* plist, DuLNode* ptr)
{
assert(plist != nullptr);
if(ptr == nullptr) return ;
if(!IsEmpty(plist))
{
DuLNode* p = ptr;
p->prev->next = p->next;
p->next->prev = p->prev;
plist->cursize -= 1;
Freenode(p);
}
}
11.头删法函数:
void Pop_front(DuLinkList* plist)
{
assert(plist != nullptr);
Erase(plist, plist->head->next);
}
12.尾删法函数:
void Pop_back(DuLinkList* plist)
{
assert(plist != nullptr);
Erase(plist, plist->head->prev);
}
13.按值删除指定节点 函数:
void Remove(DuLinkList* plist, ElemType val)
{
assert(plist != nullptr);
DuLNode* p = FindValue(plist, val);
if (p != nullptr)
{
Erase(plist, p);
}
}
14.清空链表函数:
void ClearList(DuLinkList* plist)
{
assert(plist != nullptr);
while(plist->cursize)
{
Pop_front(plist);
}
}
15.销毁链表函数:
void DestroyList(DuLinkList* plist)
{
assert(plist != nullptr);
ClearList(plist);
Freenode(plist->head);
plist->head = nullptr;
}
16.打印链表函数:
循环双链表是一个环,while循环条件不能像单链表一样 (尾结点后继不为空指针)
void PrintList(DuLinkList* plist)
{
assert(plist != nullptr);
DuLNode* p = plist->head->next;
while (p != plist->head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}