单链表有很多结构循环单链表,有头节点的单链表,无头节点的单链表,双节点单链表,以下源码是以有一个头节点的单链表为例写的增删改查的各种功能,就是下图
然后各个注释也在函数后面写着,这玩意确实还挺难,源码均已测试,vs2019运行妥妥的
废话不多说直接来看全部源码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
typedef int ElemType; //后期修改程序方便
typedef struct ListNode //定义结构体
{
ElemType data;
struct ListNode* next;
}ListNode;
typedef struct //头节点
{
struct ListNode* head;
int cursize;
}LinkList;
struct ListNode* BuyNode() //购买节点,用malloc向堆区申请空间
{
struct ListNode* s = (struct ListNode*)malloc(sizeof(struct ListNode));
if (NULL == s)
{
exit(1);
}
memset(s, 0, sizeof(struct ListNode));
return s;
};
void FreeNode(struct ListNode* p) //堆区申请完之后必须得free
{
free(p);
}
int GetSize(const LinkList* plist) //获得cursize的大小
{
assert(plist != NULL);
return plist->cursize;
}
bool IsEmpty(const LinkList* plist) //判断cursize是否为空
{
assert(plist != NULL);
return GetSize(plist) == 0;
}
void InitList(LinkList* plist) //初始化函数,malloc购买节点之后用memset初始化为0
{
assert(plist != NULL);
plist->head = BuyNode();
plist->cursize = 0;
}
void Print(LinkList* plist) //输出函数
{
assert(plist != NULL);
ListNode* p = plist->head->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
ListNode* FindeValue(LinkList* plist, ElemType val) //找到当前值的地址
{
assert(plist != NULL);
ListNode* p = plist->head->next;
while (plist != NULL && p->data != val)
{
p = p->next;
}
return p;
}
ListNode* FindeValue_Prev(LinkList* plist, ElemType val) //查找输入val的前驱地址
{
assert(plist != NULL);
ListNode* pre = plist->head;
ListNode* p = plist->head->next;
while (p != NULL && p->data != val)
{
pre = p;
}
if (p == NULL)
{
pre = NULL;
}
return p;
}
bool Insert_Next(LinkList* plist, ListNode* ptr, ElemType val) //在ptr节点后面插入val值
{
assert(plist != NULL);
if (ptr == NULL)
{
return false;
}
ListNode* s = BuyNode();
s->next = ptr->next;
ptr->next = s;
s->data = val;
plist->cursize += 1;
return true;
}
void Push_Front(LinkList* plist, ElemType val) //头插法
{
Insert_Next(plist, plist->head, val);
}
void Push_Back(LinkList* plist, ElemType val) //尾插法
{
assert(plist != NULL);
ListNode* p = plist->head;
while (p->next != NULL)
{
p = p->next;
}
Insert_Next(plist, p, val);
}
void InsertItem(LinkList* plist, ElemType x, ElemType val) //在指定x的之后插入val值
{
assert(plist != NULL);
ListNode* p = FindeValue(plist, x);
Insert_Next(plist, p, val);
}
ListNode* FindPos(const LinkList* plist, ElemType pos) //返回当前节点
{
assert(plist != NULL);
if (pos<1 || pos>plist->cursize)
{
return NULL;
}
int i = 1;
ListNode* p = plist->head->next;
while (p!=NULL && i < pos)
{
p = p->next;
i++;
}
return p;
}
ListNode* FindPos_Prev(const LinkList* plist, ElemType pos) //返回前驱节点
{
assert(plist != NULL);
if (pos<1 || pos>plist->cursize + 1)
{
return NULL;
}
ListNode* p = plist->head;
int i = 1;
while (i < pos)
{
p = p->next;
i++;
}
return p;
}
bool Erase_Next(LinkList* plist, ListNode* ptr) //删除ptr之后的节点
{
assert(plist != NULL);
if (NULL == ptr || NULL == ptr->next) return false;
ListNode* q = ptr->next;
ptr->next = q->next;
FreeNode(q);
plist->cursize -= 1;
return true;
}
void Pop_Front(LinkList* plist) //头删法
{
assert(plist != NULL);
Erase_Next(plist, plist->head);
}
void Pop_Back(LinkList* plist) //尾删法
{
assert(plist != NULL);
ListNode* p = FindeValue_Prev(plist, plist->cursize);
Erase_Next(plist, p);
}
void MergerList(LinkList* palist, LinkList* pblist, LinkList* pclist) //两个数组的有序合并
{
assert(palist != NULL && pblist != NULL && pclist != NULL);
ListNode* pa = palist->head->next;
ListNode* pb = pblist->head->next;
ListNode* pc = pclist->head;
while (pa != NULL && pb != NULL)
{
if (pa->data >= pb->data)
{
pc->next = pb;
pb = pb->next;
}
else
{
pc->next = pa;
pa = pa->next;
}
pc = pc->next;
}
if (pa != NULL)
{
pc->next = pa;
}
else
{
pc->next = pb;
}
pclist->cursize = palist->cursize + pblist->cursize;
palist->head->next = NULL;
pblist->head->next = NULL;
}
int main()
{
int ar[] = { 12,23,34,45,56,67,78,89,90,100 };
int n = sizeof(ar) / sizeof(ar[0]);
LinkList mylist;
InitList(&mylist);
for (int i = 0; i < n; i++)
{
Push_Front(&mylist, ar[i]);
Print(&mylist);
}
return 0;
}
其中函数的复用程度较高,值得仔细学习一下,初入编程的小白一个,欢迎大家来评论区交流学习。
乾坤稳定,你我皆是黑马,加油!