目录
一.双向带头循环链表
1.结构图示及介绍
- 图示
- 基本介绍
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。
2.双向带头循环链表的结构及接口实现
(1)链表结构
typedef int LDataType;
typedef struct ListNode
{
LDataType val;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
(2)链表初始化
LTNode* LTInit( )
{
LTNode* phead = CreatNode(-1);//创建哨兵位的头结点
pphead->next = phead;
pphead->prev = phead;
return phead;
}
- 图示
(3)创建新结点
LTNode* CreatNode(LDataType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
if (newnode == NULL)
{
perror("malloc");
exit(-1);
}
newnode->val = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
(4)尾插法插入新数据
void LTPushBack(LTNode* phead, LDataType x)
{
assert(phead);
LTNode* newnode =CreatNode(x);
LTNode* tail = phead->prev;
phead->prev = newnode;
newnode->next = phead;
newnode->prev = tail;
tail->next = newnode;
}
- 图示
(5)尾删法删除新数据
void LTPopBack(LTNode* phead)
{
assert(phead);
//只剩哨兵位
assert(phead->next != phead);
LTNode* tail = phead->prev;
LTNode* tailPrev = tail->prev;
free(tail);
tailPrev->next = phead;
phead->prev = tailPrev;
}
- 图示
(5)头插法插入数据
void LTPushFront(LTNode* phead, LDataType x)
{
assert(phead);
LTNode* newnode = CreatNode(x);
newnode->next = phead->next;
phead->next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;
}
- 图示
(6)头删法删除数据
void LTPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* first = phead->next;
LTNode* second = first->next;
phead->next = second;
second->prev = phead;
free(first);
first = NULL;
}
- 图示
当只剩哨兵位的头结点时:此时继续删除结点会造成在后续继续操作时出现野指针访问的情况,因此要assert(phead->next != phead)避免删除哨兵位。
(7)链表查找
LTNode* ListFind(LTNode* phead, LDataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->val == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
(8)在位置pos前插入结点
void ListInsert(LTNode* pos, LDataType x)
{
assert(pos);
LTNode* newnode = CreatNode(x);
LTNode* posPrev = pos->prev;
posPrev->next = newnode;
newnode->prev = posPrev;
newnode->next = pos;
pos->prev = newnode;
}
- 图示
(9)删除pos位置处的结点
void ListErase(LTNode* pos, LDataType x)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* posNext = pos->next;
posPrev->next = posNext;
posNext->prev = posPrev;
free(pos);
pos = NULL;
}
- 图示
(10)销毁链表
void LTDestroy(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
phead = NULL;
}