目录
一、起始设置
二、函数实现
1. 创造节点
2. 打印链表
3. 尾插尾删
4. 头插头删
5. 查找
6. 插入(前插)和删除
7. 后插和后删
8. 销毁链表
三、代码汇总
1. SList.c
2. SList.c
3. test.c
链表的本质:通过一个个的节点来记录数据,并且通过下一个节点的地址来找到下一个节点
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLT;
这里对于指针的应用非常灵活,需要补充一部分【指针知识】
1) 因为在传参的时候,我们传的都是第一个节点的指针,所以形参是一级指针的时候就只是一份临时拷贝,函数内的操作不改变原来的链表
2) 而如果是头插头删、尾插尾删等需要改变实参的函数,就需要传二级指针,二级指针就是指针的指针,也就是用来存放指针的地址的玩意
void SListPrint(SLT* plist);
SLT* SListFind(SLT* plist, SLTDataType x);
void SListDestroy(SLT** pphead);
void SListPushBack(SLT** plist, SLTDataType x);
void SListPushFront(SLT** plist, SLTDataType x);
void SListPopBack(SLT** plist);
void SListPopFront(SLT** plist);
void SListInsert(SLT** pphead, SLT* pos, SLTDataType x);
void SLTErase(SLT** pphead, SLT* pos);
void SLTInsertAfter(SLT* pos, SLTDataType x);
void SLTEraseAfter(SLT* pos);
以上函数都是放在头文件中的,还有一个只在源文件中,就是创造节点的函数,因为它只在同一文件的函数使用
SLT* CreateSListNode(SLTDataType x)
{
SLT* newNode = (SLT*)malloc(sizeof(SLTDataType));
if (newNode == NULL)
{
perror("malloc");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
return newNode;
}
void SListPrint(SLT* plist)
{
assert(plist);
while (plist)
{
printf("%d ", plist->data);
plist = plist->next;
}
}
尾插尾删、头插头删这类的函数最好画图进行分析,其实本质上思路很简单
这部分了解即可,因为效率太低(需要找到尾),一般不用
void SListPushBack(SLT** plist, SLTDataType x)
{
SLT* newNode = CreateSListNode(x);
if (*plist == NULL)
{
*plist = newNode;
(*plist)->next = NULL;
}
else
{
SLT* tail = *plist;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newNode;
}
}
void SListPopBack(SLT** plist)
{
assert(*plist);
if ((*plist)->next == NULL)
{
free(*plist);
*plist = NULL;
}
else
{
SLT* tail = *plist;
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
相比之下,头插头删是相对高效的,也是我们常用的
void SListPushFront(SLT** plist, SLTDataType x)
{
SLT* newNode = CreateSListNode(x);
newNode->next = *plist;
*plist = newNode;
}
void SListPopFront(SLT** plist)
{
assert(*plist);
SLT* tmp = *plist;
*plist = (*plist)->next;
free(tmp);//此处是否将tmp置空都可以,因为出了此函数就会被销毁
}
SLT* SListFind(SLT* plist, SLTDataType x)
{
assert(plist);
SLT* cur = plist;
while (cur)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
注意:插入的是pos的前一个位置
void SListInsert(SLT** pphead, SLT* pos, SLTDataType x)
{
assert(pos);
assert((*pphead && pos) || (!(*pphead) && !pos));
if (*pphead == pos)
{
SListPushFront(pphead, x);
}
else
{
SLT* newNode = CreateSListNode(x);
SLT* cur = *pphead;
while (cur->next != pos)
{
cur = cur->next;
}
newNode->next = pos;
cur->next = newNode;
}
}
void SLTErase(SLT** pphead, SLT* pos)
{
assert(pphead);
assert(*pphead);
assert(pos);
if (*pphead == pos)
{
SListPopFront(pphead);
}
else
{
SLT* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
void SLTInsertAfter(SLT* pos, SLTDataType x)
{
assert(pos);
SLT* newNode = CreateSListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}
void SLTEraseAfter(SLT* pos)
{
assert(pos);
assert(pos->next);
SLT* tmp = pos->next;
pos->next = tmp->next;
free(tmp);
tmp = NULL;
}
void SListDestroy(SLT** pphead)
{
assert(pphead);
assert(*pphead);
SLT* tmp = *pphead;
SLT* next = NULL;
while (tmp != NULL)
{
next = tmp->next;
free(tmp);
tmp = next;
}
*pphead = NULL;
}
总共有三个文件SList.c/SList.h/test.c,test.c可以随意调试
#pragma once
#include
#include
#include
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLT;
void SListPrint(SLT* plist);
void SListPushBack(SLT** plist, SLTDataType x);
void SListPushFront(SLT** plist, SLTDataType x);
void SListPopBack(SLT** plist);
void SListPopFront(SLT** plist);
SLT* SListFind(SLT* plist, SLTDataType x);
void SListInsert(SLT** pphead, SLT* pos, SLTDataType x);
void SLTErase(SLT** pphead, SLT* pos);
void SLTInsertAfter(SLT* pos, SLTDataType x);
void SLTEraseAfter(SLT* pos);
void SListDestroy(SLT** pphead);
#include "SList.h"
SLT* CreateSListNode(SLTDataType x)
{
SLT* newNode = (SLT*)malloc(sizeof(SLTDataType));
if (newNode == NULL)
{
perror("malloc");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
return newNode;
}
void SListPrint(SLT* plist)
{
assert(plist);
while (plist)
{
printf("%d ", plist->data);
plist = plist->next;
}
}
void SListPushBack(SLT** plist, SLTDataType x)
{
SLT* newNode = CreateSListNode(x);
if (*plist == NULL)
{
*plist = newNode;
(*plist)->next = NULL;
}
else
{
SLT* tail = *plist;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newNode;
}
}
void SListPushFront(SLT** plist, SLTDataType x)
{
SLT* newNode = CreateSListNode(x);
newNode->next = *plist;
*plist = newNode;
}
void SListPopBack(SLT** plist)
{
assert(*plist);
if ((*plist)->next == NULL)
{
free(*plist);
*plist = NULL;
}
else
{
SLT* tail = *plist;
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
void SListPopFront(SLT** plist)
{
assert(*plist);
SLT* tmp = *plist;
*plist = (*plist)->next;
free(tmp);
}
SLT* SListFind(SLT* plist, SLTDataType x)
{
assert(plist);
SLT* cur = plist;
while (cur)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
void SListInsert(SLT** pphead, SLT* pos, SLTDataType x)
{
assert(pos);
assert((*pphead && pos) || (!(*pphead) && !pos));
if (*pphead == pos)
{
SListPushFront(pphead, x);
}
else
{
SLT* newNode = CreateSListNode(x);
SLT* cur = *pphead;
while (cur->next != pos)
{
cur = cur->next;
}
newNode->next = pos;
cur->next = newNode;
}
}
void SLTErase(SLT** pphead, SLT* pos)
{
assert(pphead);
assert(*pphead);
assert(pos);
if (*pphead == pos)
{
SListPopFront(pphead);
}
else
{
SLT* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
void SLTInsertAfter(SLT* pos, SLTDataType x)
{
assert(pos);
SLT* newNode = CreateSListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}
void SLTEraseAfter(SLT* pos)
{
assert(pos);
assert(pos->next);
SLT* tmp = pos->next;
pos->next = tmp->next;
free(tmp);
tmp = NULL;
}
void SListDestroy(SLT** pphead)
{
assert(pphead);
assert(*pphead);
SLT* tmp = *pphead;
SLT* next = NULL;
while (tmp != NULL)
{
next = tmp->next;
free(tmp);
tmp = next;
}
*pphead = NULL;
}
#include "SList.h"
void Test()
{
SLT* psl = NULL;
SListPushBack(&psl, 1);
SListPushBack(&psl, 2);
SListPushBack(&psl, 3);
SLT* pos = SListFind(psl, 2);
SLT* pos2 = SListFind(psl, 3);
SListInsert(&psl, pos, 99);
SListPrint(psl);
printf("\n");
SLTErase(&psl, pos);
SLTInsertAfter(pos2, 666);
SListPrint(psl);
printf("\n");
SLTEraseAfter(pos2);
SListPrint(psl);
SListDestroy(&psl);
}
int main()
{
Test();
return 0;
}