我们来看一个最适合保存数据的链表——双向带头循环链表:
它首尾相接:这就保证了它只有一个结点时候也不算特殊情况
它两两结点相接:适合删除插入元素(时间复杂度都是O(1))
初始化:
//得先开辟空间
ListNode* BuyListNode(LTDataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
//才能初始化
ListNode* ListInit()
{
ListNode* phead = BuyListNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
插入:
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
//找到 pos 前一个结点
ListNode* prev = pos->prev;
//创建新结点
ListNode* newnode = BuyListNode(x);
//链接 prev - newnode - pos
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
删除:
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
//链接prev next
prev->next = next;
next->prev = prev;
free(pos);
pos = NULL;
}
查找:
ListNode* ListFind(ListNode* phead, LTDataType x)
{
assert(phead);
//创建结点记录x的位置
ListNode* cur = phead->next;
//遍历链表
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
释放:
void ListDestory(ListNode* phead)
{
assert(phead);
ListNode* cur = phead->next;
while (cur != phead)
{
//!!! 先保存下一个结点,再释放
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
phead = NULL;
}
打印:
void ListPrint(ListNode* phead)
{
assert(phead);
ListNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}