目录
1. 顺序表的缺陷
2. 单链表
2.1 单链表的基本结构与接口函数
2.2 重要接口
创建新节点的函数:
2.2.1 尾插
2.2.2 头插
2.2.3 尾删
2.2.4 头删
2.2.5 查找
2.2.6 插入
2.2.7 删除
2.2.8 从pos后面插入
2.2.9 从pos后面删除
3. 链表的缺陷与优势:
4. 链表与顺序表比较
写在最后:
1. 顺序表的缺陷
为什么会有链表?
我们都有顺序表来存储数据了,
因为顺序表是有缺陷的:
1. 中间头部插入删除数据,需要挪动数据,效率低下。
2. 空间不够需要扩容,扩容会有一定的消耗,也可能会造成空间的浪费。
这时候,我们就要用到链表。
2. 单链表
链表是一种物理存储结构上非连续、非顺序的存储结构,
数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
如下图:
2.1 单链表的基本结构与接口函数
基本结构:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataType;
typedef struct SListNode
{
SLDataType data;
struct SListNode* next;
}SLNode;
//打印链表
void SLPrint(SLNode* phead);
//尾插
void SLPushBack(SLNode** pphead, SLDataType x);
//头插
void SLPushFront(SLNode** pphead, SLDataType x);
//尾删
void SLPopBack(SLNode** ppheadx);
//头删
void SLPopFront(SLNode** pphead);
//查找
SLNode* SLFind(SLNode* phead, SLDataType x);
//插入
void SLInsert(SLNode** phead, SLNode* pos, SLDataType x);
//删除
void SLErase(SLNode** phead, SLNode* pos);
//从pos后面插入
void SLInsertAfter(SLNode* pos, SLDataType x);
//从pos后面删除
void SLEraseAfter(SLNode* pos);
2.2 重要接口
创建新节点的函数:
//建立一个新节点(重复操作写成函数复用)
SLNode* BuyNewNode(SLDataType x)
{
//malloc一个链表节点大小的空间
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
//检查
if (newnode == NULL)
{
perror("malloc::fail");
return;
}
//赋值
newnode->data = x;
newnode->next = NULL;
return newnode;
}
2.2.1 尾插
//尾插
void SLPushBack(SLNode** pphead, SLDataType x)
{
//检查二级指针pphead地址是否为空
//方便检查是否传空指针了
assert(pphead);
//创建节点
SLNode* newnode = BuyNewNode(x);
//如果链表为空
if (*pphead == NULL)
{
*pphead = newnode;
}
else//如果链表不为空
{
//找尾
SLNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
//尾插
tail->next = newnode;
}
}
2.2.2 头插
//头插
void SLPushFront(SLNode** pphead, SLDataType x)
{
//检查二级指针pphead地址是否为空
//方便检查是否传空指针了
assert(pphead);
//创建节点
SLNode* newnode = BuyNewNode(x);
//头插
newnode->next = *pphead;
*pphead = newnode;
}
2.2.3 尾删
//尾删
void SLPopBack(SLNode** pphead)
{
//检查二级指针pphead地址是否为空
//方便检查是否传空指针了
assert(pphead);
//检查链表是否为空
assert(*pphead);
//头删的情况(链表只有一个数据)
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
//找尾
SLNode* tail = *pphead;
while (tail->next->next != NULL)
{
tail = tail->next;
}
//尾删
free(tail->next);
tail->next = NULL;
}
}
2.2.4 头删
//头删
void SLPopFront(SLNode** pphead)
{
//检查二级指针pphead地址是否为空
//方便检查是否传空指针了
assert(pphead);
//检查链表是否为空
assert(*pphead);
//头删
SLNode* cur = (*pphead)->next;
free(*pphead);
*pphead = NULL;
*pphead = cur;
}
2.2.5 查找
//查找
SLNode* SLFind(SLNode* phead, SLDataType x)
{
//创建指针遍历链表
SLNode* cur = phead;
//查找
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
2.2.6 插入
//插入
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x)
{
//检查查找的地址是否为空
assert(pos);
//pos的位置
if (pos == *pphead)
{
SLPushFront(pphead, x);
}
else//在链表中间
{
SLNode* prev = *pphead;
//查找pos对应位置
while (prev->next != pos)
{
prev = prev->next;
}
//插入
SLNode* newnode = BuyNewNode(x);
prev->next = newnode;
newnode->next = pos;
}
}
2.2.7 删除
//删除
void SLErase(SLNode** pphead, SLNode* pos)
{
//检查二级指针pphead地址是否为空
//方便检查是否传空指针了
assert(pphead);
//检查查找的地址是否为空
assert(pos);
//检查链表是否为空(这里其实不断言也可以)
assert(*pphead);
//头删的情况
if (*pphead == pos)
{
SLPopFront(pphead);
}
else
{
//查找
SLNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
//删除
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
2.2.8 从pos后面插入
//从pos后面插入
void SLInsertAfter(SLNode* pos, SLDataType x)
{
//检查查找的地址是否为空
assert(pos);
//创建节点
SLNode* newnode = BuyNewNode(x);
//再pos后面插入
newnode->next = pos->next;
pos->next = newnode;
}
2.2.9 从pos后面删除
//从pos后面删除
void SLEraseAfter(SLNode* pos)
{
//检查查找的地址和要删除的地址是否为空
assert(pos);
assert(pos->next);
//在pos后面删除,prev记住要删除的节点,然后free
SLNode* prev = pos->next;
pos->next = prev->next;
free(pos->next);
prev = NULL;
}
这就是单链表的基本框架和接口了,
如果感兴趣,你也可以使用接口函数玩一玩。
3. 链表的缺陷与优势:
但是链表是有缺陷的,
我们可以看到,
1. 链表想要访问一个节点,就得遍历链表,
2. 链表的尾删也需要遍历链表,
3. 而链表的优势是头删很方便是O(1)。
4. 链表与顺序表比较
我们就能跟顺序表比较一下,
1. 顺序表头插需要挪动数据是O(N),
2. 但是顺序表能随机访问。
写在最后:
以上就是本篇文章的内容了,感谢你的阅读。
如果喜欢本文的话,欢迎点赞和评论,写下你的见解。
如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。文章来源:https://www.toymoban.com/news/detail-797561.html
之后我还会输出更多高质量内容,欢迎收看。文章来源地址https://www.toymoban.com/news/detail-797561.html
到了这里,关于数据结构-链表-单链表(3)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!