目录
1.带头双向循环链表
当链表为NULL的状态是:
带头循环链表是逻辑最复杂的,但是实现起来是最简单的和实用的
2.带头双向循环链表的声明
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* next;
struct ListNode* prev;
LTDataType data;
}LTNode;
// 创建返回链表的头结点.
LTNode* BuyListNode(LTDataType x);
//初始化
LTNode* ListInit();
// 双向链表打印
void LTPrint(LTNode* phead);
// 双向链表尾插
void LTPushBack(LTNode* phead, LTDataType x);
// 双向链表尾删
void LTPopBack(LTNode* phead);
// 双向链表头插
void LTPushFront(LTNode* phead, LTDataType x);
// 双向链表头删
void LTPopFront(LTNode* phead);
// 双向链表查找
ListNode* LTFind(LTNode* phead, LTDataType x);
// 双向链表在pos的前面进行插入
void LTInsert(LTNode* pos, LTDataType x);
// 双向链表删除pos位置的结点
void LTErase(LTNode* pos);
//判空
bool LTEmpty(LTNode* phead);
//判断链表的大小size
size_t LTSize(LTNode* phead);
// 双向链表销毁
void LTDestory(LTNode** phead);
3.接口函数的实现
1)创建返回链表的头结点
LTNode* BuyListNode(LTDataType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
2)初始化
LTNode* ListInit()
{
LTNode* phead = BuyListNode(-1);
phead->next = phead;
phead->prev = phead;
return phead;
}
由于初始化需要改变结构体,就需要用的二级指针
但因为有头结点的存在,其他接口函数上是不会改变结构体的,所以都用一级指针
为了统一好看一点,我们初始化也用一级指针
那我们就可以用返回值的方式进行处理
3) 打印
void LTPrint(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("\n");
}
4)尾插
void LTPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* node = BuyListNode(x);
node->next = phead;
node->prev = phead->prev;
phead->prev->next = node;
phead->prev = node;
}
5)尾删
void LTPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* tail = phead->prev;
phead->prev->prev->next = phead;
phead->prev = phead-&