一、基础知识
链表有① 带头、不带头 ② 双向、单向 ③ 循环、不循环 一共
2
3
2^3
23种情况,其中结构最简单的是:不带头单向不循环链表,结构最复杂同时实现最简单的是:带头双向循环链表。带头双向循环链表这一结构是STL中list
的结构。
带头双向循环链表结构如图所示:
- 特殊情况:只有头节点
二、接口
结构体:
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
2.1 初始化
//初始化
LTNode* ListInit()
{
LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
phead->next = phead;
phead->prev = phead;
return phead;
}
2.2 创建新结点
//创建新结点
LTNode* BuyListNode(DataType x)
{
LTNode* newNode = (LTNode*)malloc(sizeof(LTNode));
newNode->data = x;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
2.3 找
//找
LTNode* ListFind(LTNode* phead, DataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
找结点要注意迭代的结束条件,当
cur==phead
时结束寻找
2.4 打印
//打印
void ListPrint(LTNode* phead)
{
assert(phead);//断言:判断phead是否为空
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
}
打印要注意迭代的结束条件,当
cur==phead
时打印结束
2.5 头删
//头删
void ListPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* head = phead->next;
LTNode* headNext = head->next;
phead->next = headNext;
headNext->prev = phead;
free(head);
}
2.6 尾删
//尾删
void ListPopBack(LTNode* phead)
{
assert(phead);//断言:判断phead是否为空
assert(phead->next != phead);//断言:判断phead是否只有头结点
LTNode* tail = phead->prev;
LTNode* tailPrev = tail->prev;
tailPrev->next = phead;
phead->prev = tailPrev;
free(tail);
}
2.7 任意位置删除
//任意位置删除
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}
头删+尾删+中间删 = 任意删
头删也可以写成ListErase(phead->next)
尾删也可以写成ListErase(phead->prev)
2.8 头插
//头插
void ListPushFront(LTNode* phead, DataType x)
{
assert(phead);
LTNode* head = phead->next;
LTNode* newNode = BuyListNode(x);
newNode->prev = phead;
phead->next = newNode;
head->prev = newNode;
newNode->next = head;
}
2.9 尾插
//尾插
void ListPushBack(LTNode* phead, DataType x)
{
assert(phead);
LTNode* tail = phead->prev;
LTNode* newNode = BuyListNode(x);
newNode->prev = tail;
tail->next = newNode;
newNode->next = phead;
phead->prev = newNode;
}
2.10 任意位置插入
//任意位置插入
void ListInsert(LTNode* pos, DataType x)
{
assert(pos);
//找到pos前一个结点
LTNode* posPrev = pos->prev;
//新建结点
LTNode* newNode = BuyListNode(x);
//连接
newNode->prev = posPrev;
posPrev->next = newNode;
newNode->next = pos;
pos->prev = newNode;
}
头插+尾插+中间插 = 任意插
头插也可以写成ListInsert(phead->next)
尾插也可以写成ListInsert(phead->prev)