2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】

本文涉及的产品
视觉智能开放平台,视频通用资源包5000点
视觉智能开放平台,图像通用资源包5000点
视觉智能开放平台,分割抠图1万点
简介: 数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!

欢迎各位彦祖与热巴畅游本人专栏与博客

你的三连是我最大的动力

以下图片仅代表专栏特色 [点击箭头指向的专栏名即可闪现]

专栏跑道一

➡️网络空间安全——全栈前沿技术持续深入学习

image.gif

专栏跑道二

➡️ 24 Network Security -LJS

image.gif

image.gif

image.gif

专栏跑道三


➡️ MYSQL REDIS Advance operation

image.gif

专栏跑道四

➡️HCIP;H3C-SE;CCIP——LJS[华为、华三、思科高级网络]

image.gif

专栏跑道五

➡️RHCE-LJS[Linux高端骚操作实战篇]

image.png

专栏跑道六

➡️数据结构与算法[考研+实际工作应用+C程序设计]

image.gif

专栏跑道七

➡️RHCSA-LJS[Linux初级及进阶骚技能]

image.gif

image.gif

上节回顾






(1)题目:设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。

解题思路:

>利用递归,不断将节点的下个节点传入函数
>每个函数执行对应删除操作
image.gif

实现代码:

#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
    int data;           // 节点数据
    struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList 是 LNode 指针类型的别名
// 头插法构建链表
void HeadInsert(LinkList &L)
{
    int val = 0;
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        s->next = L->next;   // 新节点的next指向当前头节点的下一个节点
        L->next = s;         // 头指针的next指向新节点
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 尾插法构建链表
void TailInsert(LinkList &L)
{
    int val = 0;
    LNode *r = L; // r为指向链表最后一个节点的指针
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        r->next = s;         // 尾节点的next指向新节点
        r = s;               // r更新为新节点
        r->next = NULL;      // 新节点的next设为nullptr
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 遍历输出链表元素
void Print(LinkList L)
{
    LNode *p = L->next; // 从头节点的下一个节点开始遍历
    while (p) // 当p不为空时
    {
        cout << p->data << '\t'; // 输出节点数据
        p = p->next;             // 移动到下一个节点
    }
    cout << endl; // 输出换行
}
// 删除链表中所有值为x的节点
void DelValue(LinkList &L, int x)
{
    if (L == NULL) // 如果链表为空,直接返回
    {
        return;
    }
    LNode *p;
    // 如果当前节点的值等于x
    if (L->data == x)
    {
        p = L;            // 将当前节点赋值给p
        L = L->next;     // 将链表的头指针指向下一个节点
        delete p;        // 删除当前节点
        DelValue(L, x);  // 递归调用,继续删除后面的节点
    }
    else
    {
        DelValue(L->next, x); // 否则,递归到下一个节点
    }
}
int main()
{
    LinkList L = new LNode; // 创建链表头节点
    L->next = NULL; // 初始化头节点的next指针为NULL
    TailInsert(L); // 调用尾插法插入数据
    DelValue(L, 2); // 删除值为2的节点
    Print(L);       // 打印链表
}
image.gif

image.gif 编辑

(2)题目:在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法以实现上述操作。

解题思路:

>定义工作指针p、前驱指针pre
>遍历链表,删除元素
image.gif

实现代码:

#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
    int data;           // 节点数据
    struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList 是 LNode 指针类型的别名
// 头插法构建链表
void HeadInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        s->next = L->next;   // 新节点的next指向当前头节点的下一个节点
        L->next = s;         // 头指针的next指向新节点
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 尾插法构建链表
void TailInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    LNode *r = L; // r指向链表的尾节点
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        r->next = s;         // 尾节点的next指向新节点
        r = s;               // r更新为新节点
        r->next = NULL;      // 新节点的next设为NULL
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 遍历输出链表元素
void Print(LinkList L)
{
    LNode *p = L->next; // 从头节点的下一个节点开始遍历
    while (p) // 当p不为空时
    {
        cout << p->data << '\t'; // 输出节点数据
        p = p->next;             // 移动到下一个节点
    }
    cout << endl; // 输出换行
}
// 删除链表中所有值为x的节点
void DelValue(LinkList &L, int x)
{
    LNode *p, *pre; // p指向当前节点,pre指向前一个节点
    p = L->next; // 从头节点的下一个节点开始
    pre = L;     // pre初始化为头节点
    while (p) // 当p不为空时
    {
        if (p->data == x) // 如果当前节点的值等于x
        {
            LNode *q = p; // 将当前节点赋值给q
            pre->next = p->next; // 前一个节点的next指向当前节点的下一个节点
            p = p->next; // p移动到下一个节点
            delete q;    // 删除当前节点
        }
        else // 当前节点的值不等于x
        {
            pre = p;     // 更新前一个节点为当前节点
            p = p->next; // p移动到下一个节点
        }
    }
}
int main()
{
    LinkList L = new LNode; // 创建链表头节点
    L->next = NULL; // 初始化头节点的next指针为NULL
    TailInsert(L);  // 调用尾插法插入数据
    DelValue(L, 2); // 删除值为2的节点
    Print(L);       // 打印链表
}
image.gif

(3)题目:设L 为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。

解题思路:

>利用递归栈进行实现
>栈的特性是后进先出
>所以可以采用递归实现
image.gif

实现代码:

#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
    int data;           // 节点数据
    struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList 是 LNode 指针类型的别名
// 头插法构建链表
void HeadInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        s->next = L->next;   // 新节点的next指向当前头节点的下一个节点
        L->next = s;         // 头指针的next指向新节点
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 尾插法构建链表
void TailInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    LNode *r = L; // r指向链表的尾节点
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        r->next = s;         // 尾节点的next指向新节点
        r = s;               // r更新为新节点
        r->next = NULL;      // 新节点的next设为NULL
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 遍历输出链表元素
void Print(LinkList L)
{
    LNode *p = L->next; // 从头节点的下一个节点开始遍历
    while (p) // 当p不为空时
    {
        cout << p->data << '\t'; // 输出节点数据
        p = p->next;             // 移动到下一个节点
    }
    cout << endl; // 输出换行
}
// 递归逆序打印链表
void ReversePrint(LinkList &L)
{
    if (L == NULL) // 如果链表为空,直接返回
    {
        return;
    }
    ReversePrint(L->next); // 递归调用,先打印后面的节点
    cout << L->data << '\t'; // 打印当前节点的数据
}
int main()
{
    LinkList L = new LNode; // 创建链表头节点
    L->next = NULL;         // 初始化头节点的next指针为NULL
    TailInsert(L);          // 调用尾插法插入数据
    // 逆序打印链表的元素
    ReversePrint(L->next); 
}
image.gif

(4)题目:试编写在带头结点的单链表L 中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。

解题思路:

>定义工作指针p、pre
>定义用于保存最小值的指针minP、minPre
>遍历链表找到最小值,用指针标记
>最后修改指针将其删除释放空间
image.gif

实现代码:

#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
    int data;           // 节点数据
    struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList 是 LNode 指针类型的别名
// 头插法构建链表
void HeadInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        s->next = L->next;   // 新节点的next指向当前头节点的下一个节点
        L->next = s;         // 头指针的next指向新节点
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 尾插法构建链表
void TailInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    LNode *r = L; // r指向链表的尾节点
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        r->next = s;         // 尾节点的next指向新节点
        r = s;               // r更新为新节点
        r->next = NULL;      // 新节点的next设为NULL
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 遍历输出链表元素
void Print(LinkList L)
{
    LNode *p = L->next; // 从头节点的下一个节点开始遍历
    while (p) // 当p不为空时
    {
        cout << p->data << '\t'; // 输出节点数据
        p = p->next;             // 移动到下一个节点
    }
    cout << endl; // 输出换行
}
// 删除链表中的最小值节点
void DelMinValue(LinkList &L)
{
    // 工作节点
    LNode *p, *pre; // p是当前节点,pre是前驱节点
    p = L->next;     // 从链表的第一个节点开始
    pre = L;        // 前驱节点初始化为头节点
    // 用于保存最值的节点
    LNode *minP, *minPre; // minP是当前最小值节点,minPre是其前驱节点
    minP = p; // 初始化为第一个节点
    minPre = pre; // 初始化为头节点
    // 遍历链表查找最小值节点
    while (p)
    {
        if (p->data < minP->data) // 找到更小的值
        {
            minPre = pre; // 更新前驱节点
            minP = p;     // 更新最小值节点
        }
        pre = p; // 前驱节点向后移动
        p = p->next; // 当前节点向后移动
    }
    // 删除最小值节点
    minPre->next = minP->next; // 将前驱节点的next指向最小值节点的下一个节点
    delete minP; // 释放内存
}
int main()
{
    LinkList L = new LNode; // 创建链表头节点
    L->next = NULL;         // 初始化头节点的next指针为NULL
    TailInsert(L);          // 调用尾插法插入数据
    DelMinValue(L);         // 删除链表中的最小值节点
    Print(L);               // 打印修改后的链表
}
image.gif

(5)题目:试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为 O(1)。

解题思路:

>头插法
image.gif

实现代码:

#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
    int data;           // 节点数据
    struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList 是 LNode 指针类型的别名
// 头插法构建链表
void HeadInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        s->next = L->next;   // 新节点的next指向当前头节点的下一个节点
        L->next = s;         // 头指针的next指向新节点
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 尾插法构建链表
void TailInsert(LinkList &L)
{
    int val = 0; // 用于存储输入值
    LNode *r = L; // r指向链表的尾节点
    while (cin >> val) // 从标准输入读取数据
    {
        LNode *s = new LNode; // 创建新节点
        s->data = val;        // 设置节点数据
        r->next = s;         // 尾节点的next指向新节点
        r = s;               // r更新为新节点
        r->next = NULL;      // 新节点的next设为NULL
        // 如果读取到换行符,结束输入
        if (cin.get() == '\n')
        {
            break;
        }
    }
}
// 遍历输出链表元素
void Print(LinkList L)
{
    LNode *p = L->next; // 从头节点的下一个节点开始遍历
    while (p) // 当p不为空时
    {
        cout << p->data << '\t'; // 输出节点数据
        p = p->next;             // 移动到下一个节点
    }
    cout << endl; // 输出换行
}
// 反转链表
void fn(LinkList &L)
{
    LNode *p, *r; // p用于遍历链表,r用于保存当前节点的下一个节点
    p = L->next;  // 从头节点的下一个节点开始
    L->next = NULL; // 初始化头节点的next为NULL,准备反转
    // 反转链表
    while (p)
    {
        r = p->next; // 保存当前节点的下一个节点
        p->next = L->next; // 将当前节点的next指向当前头节点的next
        L->next = p; // 更新头节点的next为当前节点
        p = r; // 移动到下一个节点
    }
}
int main()
{
    LinkList L = new LNode; // 创建链表头节点
    TailInsert(L);          // 调用尾插法插入数据
    fn(L); // 反转链表
    Print(L); // 打印反转后的链表
}
image.gif























相关文章
|
1月前
|
机器学习/深度学习 算法 C++
【DFS/回溯算法】2016年蓝桥杯真题之路径之谜详解
题目要求根据城堡北墙和西墙箭靶上的箭数,推断骑士从西北角到东南角的唯一路径。每步移动时向正北和正西各射一箭,同一格不重复经过。通过DFS回溯模拟“拔箭”过程,验证路径合法性。已知箭数约束路径唯一,最终按编号输出行走顺序。
|
3月前
|
机器学习/深度学习 算法 数据挖掘
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
146 0
|
3月前
|
算法
回溯算法的基本思想
本节介绍回溯算法,通过图1中从A到K的路径查找示例,说明其与穷举法的异同。回溯算法通过“回退”机制高效试探各种路径,适用于决策、优化和枚举问题。
97 0
|
2月前
|
机器学习/深度学习 运维 算法
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
187 1
|
4月前
|
存储 缓存 算法
什么是回溯算法
回溯算法是一种通过尝试所有可能路径寻找问题解的策略,采用深度优先搜索与状态重置机制。它适用于组合、排列、棋盘等需枚举所有可能解的问题,核心思想包括DFS遍历、剪枝优化与状态恢复。尽管时间复杂度较高,但通过合理剪枝可显著提升效率,是解决复杂搜索问题的重要方法。
204 0
|
8月前
|
算法 数据可视化 开发者
为什么要学习数据结构与算法
今天,我向大家介绍一门非常重要的课程——《数据结构与算法》。这门课不仅是计算机学科的核心,更是每一位开发者从“小白”迈向“高手”的必经之路。
为什么要学习数据结构与算法
|
8月前
|
算法 Java
算法系列之回溯算法求解数独及所有可能解
数独求解的核心算法是回溯算法。回溯算法是一种通过逐步构建解决方案并在遇到冲突时回退的算法。具体来说,我们尝试在空格中填入一个数字,然后递归地继续填充下一个空格。如果在某个步骤中发现无法继续填充,则回退到上一步并尝试其他数字。
310 11
算法系列之回溯算法求解数独及所有可能解
|
9月前
|
算法 Java
算法系列之回溯算法
回溯算法(Backtracking Algorithm)是一种通过穷举来解决问题的方法,它的核心思想是从一个初始状态出发,暴力搜索所有可能的解决方案,遇到正确解将其记录,直到找到了所有的解或者尝试了所有的可能为止。
282 4
算法系列之回溯算法
|
10月前
|
负载均衡 算法
架构学习:7种负载均衡算法策略
四层负载均衡包括数据链路层、网络层和应用层负载均衡。数据链路层通过修改MAC地址转发帧;网络层通过改变IP地址实现数据包转发;应用层有多种策略,如轮循、权重轮循、随机、权重随机、一致性哈希、响应速度和最少连接数均衡,确保请求合理分配到服务器,提升性能与稳定性。
2164 11
架构学习:7种负载均衡算法策略
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】

热门文章

最新文章