数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁

简介: 数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁

线性表之单链表(上)

创建新结点

继续单链表的其他接口函数之前,先定义一个创建新结点的函数,方便后续使用。

SLTNode* CreateListNode(SLTDataType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}

单链表的头插函数

相比于之前的尾插函数,头插函数较简单

代码实现

void SListPushFront(SLTNode ** pphead,SLTDataType x)
{
    SLTNode * newnode = CreateListNode(x);
 
    newnode->next = *pphead;
    *pphead = newnode;
}

实现思路

单链表的尾删函数

在写单链表尾删函数时,应该进行分类讨论。

分类讨论

一是链表为空时;二是链表中只有一个结点时;三是链表中大于等于2个结点时。

为什么要分类讨论呢?我们从第三种情况往回分析就可以得到答案了:

讨论完第三种情况的尾删了。看看第二种情况,这种思路是否可行:

因此将这两种情况分开来讨论的。

第一种情况则是出于严谨,没有结点时,不进行尾删。

代码实现

void SListPopBack(SLTNode** pphead)
{
    //第一种情况
    if (*pphead == NULL)
    {
        return;
    }
    //或者-> /*assert(*pphead != NULL);*/
 
    //第二种情况
    if ((*pphead)->next == NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }
 
    //第三种情况
    else
    {
        SLTNode* prev = NULL;
        SLTNode* tail = *pphead;
        while (tail->next)
        {
            prev = tail;
            tail = tail->next;
        }
        free(tail);
        tail = NULL;
        prev->next = NULL;
    }
}

单链表的头删函数

代码实现

void SListPopFront(SLTNode ** pphead)
{
    assert(*pphead != NULL);
    
    SLTNode *next = (*pphead)->next;
    free(*pphead);
    *pphead = next;
}

实现思路

单链表的查找函数

代码实现

SLTNode* SListFind(SLTNode* phead,SLTDataType x)
{
    SLTNode* cur = phead;
    while(cur)
    {
        if(cur->data == x)
        {
            return cur;
        }
        else
        {
            cur = cur->next;
        }
    }
    return NULL;
}

单链表查找的思路是很简单的,直接进行遍历就可以了。

需要考虑的是,当查找的目标不止存在一个时应该怎么处理:

查找多个相同目标

//假设我们要查找头结点为plist的单链表中数据是2的结点,且不止一个。
SLTNode* pos = SListFind(plist,2);
int i = 1;
while(pos) //判断pos返回的值是否为NULL,为NULL则证明已找不到
{
    printf("第%d个pos结点:%p->%d\n",i++,pos,pos->data);
    pos = SListFind(pos->next,2);//在pos的下一个位置开始查找
}

同时,运用这个函数返回值的特性,可以顺便实现修改数据的作用

修改指定结点的数据

//以之前的情景为例,我们把找到的2改为20
pos = SListFind(plist,2);
if(pos)
{
    pos->data = 20;
}

pos位置前一个结点插入数据

实现思路

代码实现

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
    SLTNode* newnode = CreateListNode(x);
    if (*pphead == pos) //当要在第一个位置的前面插入数据时,则为头插
    {
        //用头插的思路来写即可
        newnode->next = *pphead;
        *pphead = newnode;
    }
    else 
    {
        //找到pos的前一个位置
        SLTNode* posPrev = *pphead;
        while (posPrev->next != pos)
        {
            posPrev = posPrev->next;
        }
        posPrev->next = newnode;
        newnode->next = pos;
    }
}

pos位置后一个结点插入数据

代码实现

//在pos的后面插入,这个更适合用于单链表,效率也更高一些
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
    SLTNode* newnode = CreateListNode(x);
    newnode->next = pos->next;
    pos->next = newnode;
}

pos位置删除结点

代码实现

void SListErase(SLTNode** pphead, SLTNode* pos)
{
    if (*pphead == pos)
    {
        //直接使用头删函数
        SListPopFront(pphead);
    }
    else
    {
        SLTNode* prev = *pphead;
        while (prev->next != pos)//与之前类似,找结点
        {
            prev = prev->next;
        }
        prev->next = pos->next;
        free(pos);
        pos = NULL;
    }
}

pos位置后删除结点

void SListEraseAfter(SLTNode* pos)
{
    assert(pos->next);
 
    SLTNode* next = pos->next;
    pos->next = next->next;
    free(next);
    //next = NULL;
}

单链表的销毁

void SListDestory(SLTNode** pphead)
{
    assert(pphead);
 
    SLTNode* cur = *pphead;
    while (cur)
    {
        SLTNode* next = cur->next;
        free(cur);
        cur = next;
    }
    *pphead = NULL;
}
目录
相关文章
|
7月前
|
算法 数据可视化 开发者
为什么要学习数据结构与算法
今天,我向大家介绍一门非常重要的课程——《数据结构与算法》。这门课不仅是计算机学科的核心,更是每一位开发者从“小白”迈向“高手”的必经之路。
为什么要学习数据结构与算法
|
6月前
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
104 0
|
8月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
200 30
|
8月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
313 25
|
9月前
|
负载均衡 算法
架构学习:7种负载均衡算法策略
四层负载均衡包括数据链路层、网络层和应用层负载均衡。数据链路层通过修改MAC地址转发帧;网络层通过改变IP地址实现数据包转发;应用层有多种策略,如轮循、权重轮循、随机、权重随机、一致性哈希、响应速度和最少连接数均衡,确保请求合理分配到服务器,提升性能与稳定性。
1849 11
架构学习:7种负载均衡算法策略
|
11月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
【EMNLP2024】基于多轮课程学习的大语言模型蒸馏算法 TAPIR
阿里云人工智能平台 PAI 与复旦大学王鹏教授团队合作,在自然语言处理顶级会议 EMNLP 2024 上发表论文《Distilling Instruction-following Abilities of Large Language Models with Task-aware Curriculum Planning》。
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
132 2

热门文章

最新文章