手把手教数据结构与算法:有序线性表设计(表合并)

个人主页:

想转码的电筒人

专栏:

手把手教数据结构与算法

文章目录

有序线性表

概念

结构

问题描述

输入

输出

样例

解题步骤

结点类

链表类

insert函数

printAll函数

merge函数

test函数

完整代码


有序线性表

概念

单链表是一种物理存储结构上非连续、非顺序的存储结构,但链表在逻辑上是连续的,顺序的,而数据元素的逻辑顺序是通过链表中的指针连接次序实现的。

结构

单链表是由一个个结点组成的,结点如下图所示:

注意:单链表中的最后一个结点的next指向空,next=NULL,一个个结点串联组成了链表。

上图是为了方便大家理解,才用线条连接了结点,实际上在内存中,每个结点可能会隔得很远,每个结点右半部分就是这个结点的地址,很明显能看到这两个结点的地址并不是相邻的,因此也验证了顺序表在逻辑结构上确实是连续的,但在物理存储结构上确实是不连续的。

链表的基本操作

1.插入操作(Insert): 在指定节点之后插入新节点

2.删除操作(Delete): 删除指定位置的节点

3.访问操作(Access):获取链表中指定位置的节点值

4.获取长度(GetLength):获取链表的长度

5.搜索操作(Search): 判断链表中是否包含指定的值,搜索指定值在链表中的位置(索引)。

6.其他操作

反转链表(Reverse):将链表中的节点顺序颠倒过来。

合并链表(MergeLists):将两个链表合并成一个链表。

切分链表(SplitList):将链表从指定位置切分成两个链表。

环检测(HasCycle):检测链表中是否存在环。 找出链表中点(FindMiddle):返回链表的中间节点

有序线性表(Ordered Linear List)也是一种链表,其中的元素按照某种顺序排列。通常,这种顺序是指元素按照某个关键字的大小进行排序,下面让我们一起实现它。

问题描述

设计一个有序线性表类,要求完成初始化,插入和遍历功能,使得表内元素实现有序排列(从小到大)。同时实现合并功能,使得两个线性表能够合并为一个线性表(可能存在重复元素)。

  • 要求使用链表和泛型编程。
  • 注:不要忘了回收指针。
输入

第一行输入字符串 dtype(“int”或者”float”)表示数据存储类型。
第二行输入 int 型数据 N1(N1≥0),代表第一个线性表元素数量;
第三行输入 N1 个 dtype 型数据,每个数据由空格隔开;
第四行输入 int 型数据 N2(N2≥0),代表第二个线性表元素数量;
第五行输入 N2 个 dtype 型数据,每个数据由空格隔开;

输出

遍历第一个线性表,第一行输出其遍历结果,每个数据由空格隔开。
遍历第二个线性表,第二行输出其遍历结果,每个数据由空格隔开。
第三行输出第一个线性表和第二个线性表合并后的遍历结果,每个数据由空格隔开。

  • 注:线性表为空时仅输出换行符,每行输出的末尾没有空格。
样例

输入:

int
7 15 24 0 13 7 15 8
3 15 1 2

输出:

0 7 8 13 15 15 24
1 2 15
0 1 2 7 8 13 15 15 15 24

解题步骤

结点类

首先是链表的结点设计,可以设计出结构体 Node 表示结点,其中包含有 data 域和 next 指针,如下图:


其中 data 表示数据,其可以是简单的类型,也可以是复杂的结构体,故采用泛型编程template<typename T>。next 指针表示,下一个的指针,其指向下一个结点,通过 next 指针将各个结点链接。结点类还有构造函数,在创建结点时可以进行初始化,

template <typename T>
struct Node
{
    Node* next;
    T value;
};
链表类

链表只需要头指针用来指向链表的起点,构造函数只需让head指向空结点,析构函数则用来删除链表中所有的结点

class List
{
public:
    Node<T>* head;
    List() : head(nullptr) {
        head = new Node<T>;
        head->next = nullptr;
    };
    ~List()
    {
        Node<T>* p;
        while (head != nullptr)
        {
            p = head;
            head = head->next;
            delete p;
        }
    }
};
insert函数

向队列中插入一个节点,值为value,使得表内元素实现有序排列(从小到大)

在链表中插入结点时,若链表为空,则将该新结点作为空结点,若链表不为空,题目要求该链表为有序线性表,故需要先通过比较新插入的结点值与链表结点值,找到结点插入的位置再进行插入

void insert(T value)
{
    Node<T>* p = head;              //获得头节点指针    
    Node<T>* node = new Node<T>;    //创建新的节点
    node->value = value;
    node->next = nullptr;
    Node<T>* tem = head;
    if (p == nullptr) p->value = value;
    for (; p != nullptr;)
    {
        if (node->value > p->value)
        {
            tem = p;
            p = p->next;
        }
        else
        {
            node->next = tem->next;
            tem->next = node;
            break;
        }
    }
    if (tem && tem->next != node)
    {
        tem->next = node;
    }
}
printAll函数

遍历并输出线性表

从头指针开始遍历即可。通过一个指针从链表的第一个元素开始,依次遍历每个节点,并输出节点的值。最终在打印完成后输出换行符。

void printAll()
    /*
    函数名:printAll
    输入值:无
    功  能:遍历并输出线性表
     */
{
    Node<T>* p = head->next;
    if (p == nullptr)
    {
        cout << endl;
        return;
    }
    for (; p->next != nullptr;)
    {
        cout << p->value << " ";
        p = p->next;
    }
    cout << p->value;
    cout << endl;
}
merge函数

合并两个线性表

遍历线性表2,使用insert函数将表2的结点插入表1,即可实现表1和表2的合并

void merge(List<T>* l2)
{
    Node<T>* p = l2->head->next;
    for (; p != nullptr;)
    {
        insert(p->value);
        p = p->next;
    }
}
test函数

调用链表函数完成题目要求

void test()
{
    int N1, N2;
    T value;
    List<T> l1, l2;
    cin >> N1;
    for (; N1 > 0; N1--)
    {
        cin >> value;
        l1.insert(value);
    }
    l1.printAll();
    cin >> N2;
    for (; N2 > 0; N2--)
    {
        cin >> value;
        l2.insert(value);
    }
    l2.printAll();
    l1.merge(&l2);
    l1.printAll();
}

完整代码

#include <iostream>
using namespace std;
template <typename T>
struct Node
{
    Node* next;
    T value;
};
template <typename T>
class List
{
public:
    Node<T>* head;
    List() : head(nullptr) {
        head = new Node<T>;
        head->next = nullptr;
    };
    ~List()
    {
        Node<T>* p;
        while (head != nullptr)
        {
            p = head;
            head = head->next;
            delete p;
        }
    }

    void insert(T value)
     
    {
        Node<T>* p = head;              //获得头节点指针    
        Node<T>* node = new Node<T>;    //创建新的节点
        node->value = value;
        node->next = nullptr;
        Node<T>* tem = head;
        if (p == nullptr) p->value = value;
        for (; p != nullptr;)
        {
            if (node->value > p->value)
            {
                tem = p;
                p = p->next;
            }
            else
            {
                node->next = tem->next;
                tem->next = node;
                break;
            }
        }
        if (tem && tem->next != node)
        {
            tem->next = node;
        }
    }

    void printAll()
     
    {
        Node<T>* p = head->next;
        if (p == nullptr)
        {
            cout << endl;
            return;
        }
        for (; p->next != nullptr;)
        {
            cout << p->value << " ";
            p = p->next;
        }
        cout << p->value;
        cout << endl;
    }

    void merge(List<T>* l2)
        
    {
        Node<T>* p = l2->head->next;
        for (; p != nullptr;)
        {
            insert(p->value);
            p = p->next;
        }
    }
};
template <typename T>
void test()
{
    int N1, N2;
    T value;
    List<T> l1, l2;
    cin >> N1;
    for (; N1 > 0; N1--)
    {
        cin >> value;
        l1.insert(value);
    }
    l1.printAll();
    cin >> N2;
    for (; N2 > 0; N2--)
    {
        cin >> value;
        l2.insert(value);
    }
    l2.printAll();
    l1.merge(&l2);
    l1.printAll();
}
int main()
{
    string dtype;
    cin >> dtype;
    if (dtype == "int")
        test<int>();
    else
        test<float>();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/601711.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《构建高效的财务管理系统:设计与实现》

在当今数字化时代&#xff0c;企业财务管理系统的设计与实现至关重要。一个高效的财务管理系统不仅能够提高企业的运营效率&#xff0c;还能够增强企业的竞争力&#xff0c;为企业的发展提供有力支持。本文将探讨财务管理系统的设计与实现&#xff0c;为企业打造一套符合自身需…

WEB应用防火墙:构建稳固的网络防线

随着互联网的飞速发展&#xff0c;WEB应用已成为企业对外展示形象、提供服务的重要窗口。然而&#xff0c;随之而来的是日益严峻的网络安全威胁&#xff0c;如跨站脚本攻击&#xff08;XSS&#xff09;、SQL注入、恶意文件上传等。为了保障WEB应用的安全&#xff0c;构建一套高…

AI智能分析赋能EasyCVR视频汇聚平台,为安全生产监管提供保障

一、背景需求 为提升公共及生产安全监管&#xff0c;深入贯彻落实中央关于智慧城市、数字乡村的部署要求&#xff0c;视频设备融合管理已成为视频治理的必然趋势。针对当前部分地区在视频监控系统建设中存在的问题&#xff0c;如重点地区视频监控系统建设零散、视频监控数据孤…

普通人适合做大模型吗?过程中会发生什么潜在的挑战?

对于普通人来说&#xff0c;直接进行大模型的研发和训练可能存在一定的挑战&#xff0c;因为这通常需要以下资源和知识&#xff1a; 专业知识&#xff1a; 大模型的开发需要深入理解机器学习、深度学习、神经网络等领域的知识。 计算资源&#xff1a; 大模型的训练需要高性能的…

数组元素翻倍C++

编写一个 C 程序&#xff0c;实现一个功能&#xff0c;即将数组中的每个元素值翻倍。程序应定义一个函数 doubleArray&#xff0c;该函数接收一个整数数组的指针和数组的大小&#xff0c;然后将数组中的每个元素都翻倍。 代码 #include <iostream>void doubleArray(int…

JSON++介绍

1.简介 JSON 是一个轻量级的 JSON 解析库&#xff0c;它是 JSON&#xff08;JavaScript Object Notation&#xff09;的一个超集。整个代码由一个单独的头文件json.hpp组成&#xff0c;没有库&#xff0c;没有子项目&#xff0c;没有依赖项&#xff0c;没有复杂的构建系统&…

安防视频/视频汇聚系统EasyCVR视频融合云平台助力智能化酒店安防体系的搭建

一、背景需求 2024年“五一”假期&#xff0c;全国文化和旅游市场总体平稳有序。文化和旅游部6日发布数据显示&#xff0c;据文化和旅游部数据中心测算&#xff0c;全国国内旅游出游合计2.95亿人次。“五一”假期县域市场酒店预订订单同比增长68%&#xff0c;而酒店作为一个高…

js原生手写一个拖拽小功能

先上效果图 附上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthd…

check startup检查各种资源文件

check startup 命令功能 check startup命令用来检查各种资源文件&#xff08;paf文件、补丁包、启动软件、配置文件&#xff09;是否正确。 命令格式 check startup [ crc ] [ next ] 参数说明 参数参数说明取值 crc 对资源文件进行CRC校验。 - next 检查下一次启动的各…

Git系列:Git Switch 高效使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

用标准的GNU/Linux命令替换Alpine上的精简版命令

Alpine Linux 是一个基于 musl libc 和 busybox 的轻量级Linux发行版&#xff0c;busybox 实现了很多常用类Unix命令的精简版&#xff0c;特点是体积很小&#xff0c;舍弃了很多不常用参数&#xff0c;我们简单对比一下标准Linux自带的 date 命令 和 Alpine下默认的 date 命令便…

Golang | Leetcode Golang题解之第76题最小覆盖子串

题目&#xff1a; 题解&#xff1a; func minWindow(s string, t string) string {ori, cnt : map[byte]int{}, map[byte]int{}for i : 0; i < len(t); i {ori[t[i]]}sLen : len(s)len : math.MaxInt32ansL, ansR : -1, -1check : func() bool {for k, v : range ori {if c…

每日两题 / 138. 随机链表的复制 148. 排序链表(LeetCode热题100)

138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 用哈希表记录原链表中的节点是否被复制过 遍历原链表并通过哈希表维护新链表 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;rand…

Glowroot:Java应用的性能守护神,让监控变得既轻松又有趣!

Glowroot&#xff1a;Java应用的性能守护神&#xff0c;让监控变得既轻松又有趣&#xff01; 在这个快节奏的数字化时代&#xff0c;作为一名开发者&#xff0c;你是否曾因应用性能问题而夜不能寐&#xff1f;是不是常幻想有个超级英雄能在关键时刻挺身而出&#xff0c;帮你揪…

淘宝优惠券领取软件草柴返利APP想从淘宝粘贴提示怎么关闭?想从天猫粘贴、想从京东粘贴弹窗提示关闭

使用iPhone苹果手机想从淘宝点击分享复制链接&#xff0c;到草柴APP查询该商品内部大额隐藏优惠券和返利。可是&#xff0c;苹果iPhone手机每次将复制的商品链接&#xff0c;粘贴到草柴APP时都是提示&#xff1a;“草柴”想从“淘宝”粘贴&#xff0c;每次都需要点击允许粘贴后…

docker搭建代码审计平台sonarqube

docker搭建代码审计平台sonarqube 一、代码审计关注的质量指标二、静态分析技术分类三、sonarqube流程四、快速搭建sonarqube五、sonarqube scanner的安装和使用 一、代码审计关注的质量指标 代码坏味道 代码规范技术债评估 bug和漏洞代码重复度单测与集成 测试用例数量覆盖率…

管易云与金蝶K3-WISE对接集成发货单查询2.0打通新增销售出库(红蓝字)

管易云与金蝶K3-WISE对接集成发货单查询2.0打通新增销售出库&#xff08;红蓝字&#xff09; 源系统:管易云 金蝶管易云是金蝶集团旗下以电商和新零售为核心业务的子公司&#xff0c;公司于2008年成立&#xff0c;拥有从事电商及新零售业务相关专业知识工作者超过1000人。为伊利…

35道必懂的 Linux 运维面试题

1、现在给你三百台服务器&#xff0c;你怎么对他们进行管理&#xff1f; 管理3百台服务器的方式&#xff1a; 1&#xff09;设定跳板机&#xff0c;使用统一账号登录&#xff0c;便于安全与登录的考量。 2&#xff09;使用 salt、ansiable、puppet 进行系统的统一调度与配置的…

鸿蒙 DevEcoStudio:简单实现网络请求登录案例

使用http或axios实现登录案例 在entry/src/main/ets/pages路径下新建Page9.ets文件&#xff1a; import http from ohos.net.http import router from ohos.router Entry Component struct Page9 {State message: string Hello WorldState username: string State password:…

【网络原理】HTTP协议 | 报文格式 | Fiddler抓包 | HTTP请求 | HTTP响应 | 构造HTTP请求

文章目录 HTTP协议使用HTTP的场景&#xff1a; 一、HTTP协议的报文格式1.Fiddler的使用教程 二、HTTP请求(Request)1.首行&#xff1a;1)方法(method)GET和POST的区别(面试题) 2)URL 2.请求头&#xff08;header&#xff09;&#xff1a;1.HOST:2.Content-Length3.body中数据的…