数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、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;
}
目录
打赏
0
0
0
0
74
分享
相关文章
|
2月前
|
算法系列之递归反转单链表
递归反转链表的基本思路是将当前节点的next指针指向前一个节点,然后递归地对下一个节点进行同样的操作。递归的核心思想是将问题分解为更小的子问题,直到达到基本情况(通常是链表末尾)。
55 5
算法系列之递归反转单链表
【C++数据结构——线性表】求集合的并、交和差运算(头歌实践教学平台习题)【合集】
本任务要求编写程序求两个集合的并集、交集和差集。主要内容包括: 1. **单链表表示集合**:使用单链表存储集合元素,确保元素唯一且无序。 2. **求并集**:遍历两个集合,将所有不同元素加入新链表。 3. **求交集**:遍历集合A,检查元素是否在集合B中存在,若存在则加入结果链表。 4. **求差集**:遍历集合A,检查元素是否不在集合B中,若满足条件则加入结果链表。 通过C++代码实现上述操作,并提供测试用例验证结果。测试输入为两个集合的元素,输出为有序集合A、B,以及它们的并集、交集和差集。 示例测试输入: ``` a c e f a b d e h i ``` 预期输出:
109 7
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
214 5
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
117 5
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
135 4
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
105 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
6月前
|
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
85 6
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
6月前
01(数据结构考研)线性表相关操作代码
01(数据结构考研)线性表相关操作代码
118 0
基于和声搜索优化算法的机器工作调度matlab仿真,输出甘特图
本程序基于和声搜索优化算法(Harmony Search, HS),实现机器工作调度的MATLAB仿真,输出甘特图展示调度结果。算法通过模拟音乐家即兴演奏寻找最佳和声的过程,优化任务在不同机器上的执行顺序,以最小化完成时间和最大化资源利用率为目标。程序适用于MATLAB 2022A版本,运行后无水印。核心参数包括和声记忆大小(HMS)等,适应度函数用于建模优化目标。附带完整代码与运行结果展示。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等