大家好呀!这个是付青云同学的博客,是一名大一在校生哦!
目前一直在学习C语言。
写博客是为了来记录我的学习过程,同时也希望通过博客能够帮助到需要帮助的人。
如果我的博客可以帮助到你,不妨给我一个关注哦
前面顺序表说道:
顺序表发现它还是有缺点的:
- 空间不够了需要增容,而增容是要付出代价的;
- 所以避免频繁扩容,满了基本都是扩容两倍,但这样就可能导致一定的空间浪费;
- 顺序表要求数据从开始位置连续存储,那么我们在头部还在中间位置插入删除数据就需要挪动数据,效率不高。
于是为了解决这些问题,就有了单链表
文章目录- 单链表
- 声明部分
- 函数部分
- 总结
我创建了一个头文件(fu.h)来声明
#pragma once typedef int SLTDateType; #include函数部分#include #include #include typedef struct SListNode { SLTDateType date; struct SListNode* next; }SLTNode; //打印 void SListPrint(SLTNode* phead); //尾插 void SListPushBuck(SLTNode** pphead,SLTDateType x); //头插 void SListPushFront(SLTNode** pphead, SLTDateType x); //尾删 void SListPopBack(SLTNode** pphead); //头删 void SListPopFront(SLTNode** pphead); //查找一个值为x的地址 SLTNode* SlistFind(SLTNode* phead, SLTDateType x); //修改 //void SListRevise(SLTNode** pphead, SLTNode* pos, SLTDateType x) //或者; void SListRevise(SLTNode** pphead,int pos, SLTDateType x); //在pos位置之前插入一个节点 //void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x); //或者 void SListInsert(SLTNode** pphead, int pos, SLTDateType x); //在pos位置之后插入一个节点(简单) void SListInsertAfter(SLTNode* pos, SLTDateType x); //在pos位置删除一个节点 void SListEase(SLTNode** pphead, SLTNode* pos); //在pos位置之后删除一个节点 void SListEaseAfter(SLTNode* pos); //销毁链表 void SListDestory(SLTNode** pphead);
#define _CRT_SECURE_NO_WARNINGS
#include "fu.h"
void SListPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->date);
cur = cur->next;
}
}
//开辟新空间
SLTNode* BuyListNode(SLTDateType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
printf("malloc filn");
exit(-1);
}
newnode->date = x;
newnode->next = NULL;
return newnode;
}
void SListPushBuck(SLTNode** pphead, SLTDateType x)//注意是二级指针!
{
assert(pphead != NULL);
//插入
SLTNode* newnode = BuyListNode(x);
//第一个节点不找尾
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
//找到尾节点
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void SListPushFront(SLTNode** pphead, SLTDateType x)
{
asssert(pphead);
SLTNode* newnode = BuyListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
void SListPopBack(SLTNode** pphead)
{
assert(*pphead != NULL);
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SLTNode* prev = NULL;
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
void SListPopFront(SLTNode** pphead)
{
assert(*pphead != NULL);
SLTNode* next = *pphead;
(*pphead) = (*pphead)->next;
free(next);
}
SLTNode* SlistFind(SLTNode* phead, SLTDateType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->date == x)
{
return cur;
}
else
{
cur = cur->next;
}
}
return NULL;
}
void SListRevise(SLTNode** pphead,int pos, SLTDateType x)
{
SLTNode* cur = SlistFind(*pphead, pos);
if (cur)
{
cur->date = x;
}
}
//在pos之后插入一个节点(简单)
void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
SLTNode* newnode = BuyListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
void SListEase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
if (*pphead == pos)
{
SListPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
void SListEaseAfter(SLTNode* pos)
{
assert(pos->next != NULL);
SLTNode* next = pos;
pos->next = next->next;
free(next);
//next = NULL;
}
void SListDestory(SLTNode** pphead)
{
SLTNode* cur = *pphead;
while (cur)
{
SLTNode* next = cur->next;
free(cur);
cur = next;
}
*pphead = NULL;
}
void SListInsert(SLTNode** pphead, int pos, SLTDateType x)
{
SLTNode* newnode = BuyListNode(x);
SLTNode* cur = SlistFind(*pphead, pos);
if (*pphead == cur)
{
newnode->next = *pphead;
*pphead = newnode;
}
else
{
//找到pos的前一个位置
SLTNode* posPrev = *pphead;
while (posPrev->next != cur)
{
posPrev = posPrev->next;
}
posPrev->next = newnode;
newnode->next = cur;
}
}
之后可以自行调用函数来测试顺序表。
总结写完这个单链表发现它也是有缺点的:
- 储存空间不连续,这意味着不能使用像冒泡排序快速排序等算法
- 每一个数据,都要存一个指针去链接后面数据节点
- 要访问特定的元素,都只能从表头开始,造成资源浪费
当然,单链表也不是一无是处的,前面说了,它解决了顺序表的很多缺点。



