1. 什么是链表?
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
2. 链表的分类?
单向或双向
带头或不带头
循环或非循环
单链表实现:
1. 动态申请一个节点
// 动态申请一个节点
SListNode* BuySListNode(SLTDataType x)
{
SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
if (newNode == NULL)
{
perror("malloc failed");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
return newNode;
}
2. 单链表打印
// 单链表打印
void SListPrint(SListNode* phead)
{
SListNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
3. 单链表尾插
// 单链表尾插
void SListPushBack(SListNode** pphead, SLTDataType x)
{
SListNode* newNode = BuySListNode(x);
SListNode* tail = *pphead;
if (tail == NULL)
{
*pphead = newNode;
}
else
{
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newNode;
}
}
4. 单链表头插
// 单链表的头插
void SListPushFront(SListNode** pphead, SLTDataType x)
{
SListNode* newNode = BuySListNode(x);
newNode->next = *pphead;
*pphead = newNode;
}
5. 单链表尾删
// 单链表的尾删
void SListPopBack(SListNode** pphead)
{
assert(*pphead);
SListNode* tail = *pphead;
SListNode* tailPrev = NULL;
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
while (tail->next != NULL)
{
tailPrev = tail;
tail = tail->next;
}
free(tail);
tailPrev->next = NULL;
}
}
6. 单链表头删
// 单链表头删
void SListPopFront(SListNode** pphead)
{
assert(*pphead);
SListNode* newHead = (*pphead)->next;
free(*pphead);
*pphead = newHead;
}
7. 单链表查找
// 单链表查找
SListNode* SListFind(SListNode* phead, SLTDataType x)
{
assert(phead);
SListNode* newNode = BuySListNode(x);
SListNode* cur = phead;
while (cur != NULL)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
8. 单链表插入
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode** pphead, SListNode* pos, SLTDataType x)
{
assert(pos);
SListNode* newNode = BuySListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}
9. 单链表删除
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode** pphead, SListNode* pos)
{
assert(*pphead);
assert(pos);
SListNode* posNext = pos->next;
if (posNext != NULL)
{
pos->next = posNext->next;
}
free(posNext);
}
10. 单链表销毁
// 单链表的销毁
void SListDestroy(SListNode** pphead)
{
SListNode* cur = *pphead;
SListNode* curPrev = NULL;
while (cur != NULL)
{
curPrev = cur;
cur = cur->next;
free(curPrev);
}
*pphead = NULL;
}
双向链表实现:
1. 创建头节点
// 创建返回链表的头结点.
ListNode* ListCreate()
{
ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
phead->next = phead;
phead->prev = phead;
phead->data = -1;
return phead;
}
2. 双链表销毁
// 双向链表销毁
void ListDestory(ListNode* phead)
{
assert(phead);
ListNode* cur = phead->next;
while (cur != phead)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
}
3. 双链表打印
// 双向链表打印
void ListPrint(ListNode* phead)
{
assert(phead);
ListNode* cur = phead->next;
printf("head<=>");
while (cur != phead)
{
printf("%d<=>", cur->data);
cur = cur->next;
}
putchar('\n');
}
4. 双链表尾插
// 双向链表尾插
void ListPushBack(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
newnode->data = x;
ListNode* tail = phead->prev;
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
}
5. 双链表头插
// 双向链表头插
void ListPushFront(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
newnode->data = x;
ListNode* first = phead->next;
phead->next = newnode;
newnode->prev = phead;
newnode->next = first;
first->prev = newnode;
}
6. 双链表头删
// 双向链表头删
void ListPopFront(ListNode* phead)
{
assert(phead);
ListNode* first = phead->next;
assert(first != phead); // 至少有一个元素
phead->next = first->next;
first->next->prev = phead;
free(first);
}
7. 双链表查找
// 双向链表查找
ListNode* ListFind(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* cur = phead->next;
assert(cur != phead); // 至少有一个元素
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
8. 双链表插入
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* phead, ListNode* pos, LTDataType x)
{
assert(phead);
assert(pos); // 元素必须存在
assert(phead->next != phead); // 至少有一个元素
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
newnode->data = x;
ListNode* prev = pos->prev;
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
9. 双链表删除
// 双向链表删除pos位置的节点
void ListErase(ListNode* phead, ListNode* pos)
{
assert(phead);
assert(phead->next != phead); // 至少有一个元素
assert(pos); // 元素必须存在
ListNode* prev = pos->prev;
ListNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}