链表概念
基本结构如下图。逻辑连续,内存空间不连续
共八种,常用为两种:单链表和双向循环链表
其中带哨兵位的链表更方便使用,如下图:
即head结点位不存任何数据,这样方便头插,可以避免当更改头结点数据时必须使用二级指针的情况
1. 无头单链表
//(1) 头插
void SlistPushFront(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySLTNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
```bash
在这里插入代码片
(2) 尾插
void SlistPushBack(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuySLTNode(x);
//1.空
//2.非空
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
//找尾
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
//头删
void SlistPopFront(SLTNode** pphead)
{
assert(pphead);
//温柔的检查
/*if (*pphead == NULL)
{
return;
}*/
//暴力检查
assert(*pphead != NULL);
SLTNode* del = *pphead;
*pphead = (*pphead) -> next;
free(del);
del = NULL;
}
//尾删
void SlistPopBack(SLTNode** pphead)
{
assert(*pphead);
//检查是否头结点的地址为空
assert(*pphead != NULL);
//1.1个节点
//2.多个节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
//找尾
SLTNode* prev = NULL;
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
prev->next = NULL;
free(tail);
tail = NULL;
}
}
2. 双向链表
初始化的双向链表
//尾插
void ListPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
/*LTNode* newnode = BuySLTNode(x);
LTNode* tail = phead->prev;
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;*/
//or
ListInsert(phead, x);
}
//头插
void ListPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
/*LTNode* newnode = BuySLTNode(x);
LTNode* next = phead->next;
newnode->next = next;
next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;*/
//or
ListInsert(phead->next, x);
}
//尾删
void ListPopBack(LTNode* phead)
{
assert(phead);
assert(!ListEmpty(phead));
/*LTNode* tail = phead->prev;
LTNode* prev = tail->prev;
prev->next = phead;
phead->prev = prev;
free(tail);
tail = NULL;*/
//or
//*4*
ListErase(phead->prev);
}
//头删
void ListPopFront(LTNode* phead)
{
assert(phead);
assert(!ListEmpty(phead));
/*LTNode* delfirst = phead->next;
LTNode* first = delfirst->next;
phead->next = first;
first->prev = phead;
free(delfirst);
delfirst = NULL;*/
//or
ListErase(phead->next);
}
//在pos之前插入
void ListInsert(LTNode* pos, LTDataType x)
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* newnode = BuyLTNode(x);
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
//删除pos结点
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* first = pos->prev;
LTNode* scend = pos->next;
first->next = scend;
scend->prev = first;
free(pos);
}