<数据结构>创建一个单链表

2023-11-19

单链表基本操作的实现

内容:构建线性表的链式存储结构,采用动态分配方式实现单链表的初始化,数据的插入,删除,输出单链表内中各元素,求单链表的长度,实现单链表中数据结点的按值排序,实现单链表的逆置,合并两个有序的单链表(有序的a表和有序的b表合并之后的结果保存在a表中)等操作。
同时:
(1)要有能根据用户的输入来选择不同运算的菜单界面。
(2)单链表中数据元素的类型统一抽象表示为ElemType类型,具体类型不限,可以是整型、实型、字符型、或者是自己构造的一种结构体类型。

代码如下:

#include <iostream>
#define ElemType int
using namespace std;

//带头结点的单链表类,头结点存放单链表长度 
class Single_List {
private:
    ElemType data;
    Single_List* next;
public:

    Single_List() {};

    //单链表的创建函数,尾插法 
    Single_List* Create(int len) {
        Single_List* prev, * head, * tail;
        head = new Single_List;
        head->data = len;
        head->next = NULL;
        prev = head;
        if (len == 0) {
            goto end;
        }
        cout << "请输入各个结点的数值:" << endl;
        while (len--) {
            int data;
            tail = new Single_List;
            cin >> data;
            this->attach(prev, tail, data);
            prev = tail;
        }
    end:    return head;
    }

    void attach(Single_List* prev, Single_List* tail, int data) {
        tail->next = NULL;
        tail->data = data;
        prev->next = tail;
    }

    int getLength(Single_List* list) {
        return list->data;
    }

    //判断单链表是否为空的函数 
    bool Isempty(Single_List* list) {
        return list->data == 0;
    }

    //单链表的打印函数
    void Print(Single_List* list) {
        if (list->Isempty(list)) {
            cout << "单链表为空" << endl;
            return;
        }
        int len = list->data;
        Single_List* ptrl = list->next;
        for (int i = 0; i < len; i++) {
            cout << ptrl->data << " ";
            ptrl = ptrl->next;
        }
    }

    //在第index个结点后面插入数值为data的结点的函数 
    Single_List* Insert(Single_List* list, int index, int data) {
        Single_List* prev = list;
        Single_List* insert;
        insert = new Single_List;
        int len = list->getLength(list);
        //链表为空时,无论index为多少,只能插在第一个位置 
        if (this->Isempty(list)) {
            this->attach(prev, insert, data);
            list->data++;
            return list;
        }
        //如果插入的位置大于等于链表长度直接插到末尾, 
        index = (list->data <= index) ? list->data : index;
        for (int i = 0; i < index; i++) {
            prev = prev->next;
        }
        insert->data = data;
        insert->next = prev->next;
        prev->next = insert;
        list->data++;
        return list;
    }

    //寻找第k个结点的函数,只适用链表不为空的情况 
    Single_List* Findkth(Single_List* list, int k) {
        Single_List* prev;
        prev = list;
        for (int i = 0; i < k; i++) {
            prev = prev->next;
        }
        return prev;
    }

    //寻找数值为N的结点的函数
    int FindN(Single_List* list, int N) {
        int result = -1;
        Single_List* prev;
        prev = list;
        int len = this->getLength(list);
        for (int i = 0; i < len; i++) {
            prev = prev->next;
            if (prev->data == N) {
                result = i;
                break;
            }
        }
        return result;
    }

    //删除数值为N的结点的函数 
    void DeleteN(Single_List* list, int N) {
        int index = this->FindN(list, N);
        //不存在数值为N的情况 
        if (index == -1) {
            cout << "单链表不存在数值为" << N << "的结点" << endl;
            return;
        }
        this->Deletekth(list, index + 1);
    }

    //删除第k个结点的函数
    void Deletekth(Single_List* list, int k) {
        int len = list->data;
        if (this->Isempty(list)) {
            cout << "单链表为空无法删除" << endl;
            return;
        }
        Single_List* del_pre;
        del_pre = this->Findkth(list, k - 1);
        del_pre->next = del_pre->next->next;
        list->data--;
    }

    //逆转链表函数
    Single_List* Reverse(Single_List* list) {
        //单链表为空时 
        if (this->Isempty(list)) {
            return list;
        }
        Single_List* head, * front, * rear, * tag;
        head = list;                //保存头结点 
        //front,rear用于逆转,tag用于记录未逆转的链表 
        front = list->next;
        rear = front->next;
        front->next = NULL;
        while (rear) {
            tag = rear->next;
            rear->next = front;
            front = rear;
            rear = tag;
        }
        head->next = front;
        return head;
    }

    //对两个升序链表进行升序合并函数 
    Single_List* Merge(Single_List* list1, Single_List* list2) {
        if (list1 == NULL) {
            return list1;
        }
        if (list2 == NULL) {
            return list2;
        }
        Single_List* list;          //建立合并链表的头结点,存放两个链表长度之和 
        list = new Single_List;
        list->data = list1->data + list2->data;
        list->next = NULL;
        Single_List* prev1, * prev2, * tail, * head, * tag;
        prev1 = list1->next;        //指向list32的第一个结点(不是存放长度的头结点,即头结点之后的结点)
        prev2 = list2->next;
        head = new Single_List;     //建立新链表的空头结点 
        tag = head;                 //保存空头结点的地址 
        head->next = NULL;
        while (prev1 && prev2) {
            tail = new Single_List;
            if (prev1->data <= prev2->data) {
                this->attach(head, tail, prev1->data);
                head = tail;
                prev1 = prev1->next;
            }
            else {
                this->attach(head, tail, prev2->data);
                head = tail;
                prev2 = prev2->next;
            }
        }
        if (prev1) {
            head->next = prev1;
        }
        if (prev2) {
            head->next = prev2;
        }
        list->next = tag->next;
        return list;
    }

    //链表长
    int Length(Single_List* list)
    {
        Single_List* s = list->next;
        int length = 0;
        while (s)
        {
            s = s->next;
            length++;
        }
        cout << length << endl;
        return length;
    }

    //链表排序,冒泡排序
    Single_List* Sort(Single_List* list)
    {
        Single_List* head, * prev1, * prev2;
        head = list;
        prev1 = list->next;
        while (prev1) {
            prev2 = prev1->next;
            while (prev2) {
                if (prev1->data > prev2->data) {
                    prev1->data += prev2->data;
                    prev2->data = prev1->data - prev2->data;
                    prev1->data -= prev2->data;
                }
                prev2 = prev2->next;
            }
            prev1 = prev1->next;
        }
        return head;
    }
    void show_Menu()
    {
        cout << "请输入要进行的任务" << endl;
        cout << "0.退出程序" << endl;
        cout << "1.创建两条单链表" << endl;
        cout << "2.排序输出" << endl;
        cout << "3.插入数值" << endl;
        cout << "4.删除(结点)" << endl;
        cout << "5.删除(数值)" << endl;
        cout << "6.倒置输出" << endl;
        cout << "7.输出表长" << endl;
        cout << "8.合并两表" << endl;
        cout << endl;

    }

    void ExitSystem()
    {
        cout << "使用结束" << endl;
        system("pause");
        exit(0);
    }
    ~Single_List() {};
};

int main()
{
    int len, index, data, n;
    Single_List tmp;
    Single_List* list = NULL;
    Single_List* list1 = NULL;

    int choice = 0;
    while (true)
    {
        //展示
        tmp.show_Menu();

        cout << "请输入选择" << endl;
        cin >> choice;

        switch (choice)
        {
        case 0://退出
            tmp.ExitSystem();
            break;
        case 1://创建
            cout << "请输入初始化单链表 1 的长度:" << endl;

            cin >> len;
            list = tmp.Create(len);

            cout << "单链表如下:" << endl;
            tmp.Print(list);
            cout << endl;


            cout << "请输入初始化单链表 2 的长度:" << endl;
            cin >> len;
            list1 = tmp.Create(len);
            cout << "第二个单链表如下:" << endl;
            tmp.Print(list1);
            cout << endl;
            break;

        case 2://排序
            cout << "单链表 1 排序后为:" << endl;
            list = tmp.Sort(list);
            tmp.Print(list);
            cout << endl;

            cout << "单链表 2 排序后为:" << endl;
            list1 = tmp.Sort(list1);
            tmp.Print(list1);
            cout << endl;
            break;

        case 3://插入
            cout << "请选择进行插入操作的链表 1/2 " << endl;
            cin >> n;
            if (n == 1)
            {
                cout << "插入前单链表如下" << endl;
                tmp.Print(list);
                cout << "请输入插入结点的位置:" << endl;
                cin >> index;
                cout << "请输入插入结点的数值:" << endl;
                cin >> data;
                list = tmp.Insert(list, index, data);
                cout << "插入后单链表如下" << endl;
                tmp.Print(list);
                cout << endl;
            }
            if (n == 2)
            {
                cout << "插入前单链表如下" << endl;
                tmp.Print(list1);
                cout << "请输入插入结点的位置:" << endl;
                cin >> index;
                cout << "请输入插入结点的数值:" << endl;
                cin >> data;
                list = tmp.Insert(list1, index, data);
                cout << "插入后单链表如下" << endl;
                tmp.Print(list1);
                cout << endl;
            }
            else
            {
                cout << "   " << endl;
            }
            break;

        case 4://删除(结点)
            cout << "请选择进行删除操作的链表 1/2 " << endl;
            cin >> n;
            if (n == 1)
            {
                cout << "删除前单链表如下" << endl;
                tmp.Print(list);
                cout << "请输入删除结点的位置:" << endl;
                cin >> index;
                tmp.Deletekth(list, index);
                cout << "删除后单链表 1 如下" << endl;
                tmp.Print(list);
                cout << endl;
            }
            if (n == 2)
            {
                cout << "删除前单链表如下" << endl;
                tmp.Print(list1);
                cout << "请输入删除结点的位置:" << endl;
                cin >> index;
                tmp.Deletekth(list1, index);
                cout << "删除后单链表 1 如下" << endl;
                tmp.Print(list1);
                cout << endl;
            }
            else
            {
                cout << "   " << endl;
            }
            break;

        case 5://删除(值)
            cout << "请选择进行删除操作的链表 1/2 " << endl;
            cin >> n;
            if (n == 1)
            {
                cout << "删除前单链表如下" << endl;
                tmp.Print(list);
                cout << "请输入删除结点的数值:" << endl;
                cin >> data;
                tmp.DeleteN(list, data);
                cout << "删除后单链表 1 如下" << endl;
                tmp.Print(list);
                cout << endl;
            }
            if (n == 2)
            {
                cout << "删除前单链表如下" << endl;
                tmp.Print(list1);
                cout << "请输入删除结点的数值:" << endl;
                cin >> data;
                tmp.Deletekth(list1, data);
                cout << "删除后单链表 2 如下" << endl;
                tmp.Print(list1);
                cout << endl;
            }
            else
            {
                cout << "  " << endl;
            }
            break;

        case 6://倒置
            cout << "请选择进行删除操作的链表 1/2 " << endl;
            cin >> n;
            if (n == 1)
            {
                cout << "倒置前单链表如下" << endl;
                tmp.Print(list);
                cout << "倒置后单链表 1 如下" << endl;
                list = tmp.Reverse(list);
                tmp.Print(list);
            }
            if (n == 2)
            {
                cout << "倒置前单链表如下" << endl;
                tmp.Print(list1);
                cout << "倒置后单链表 2 如下" << endl;
                list1 = tmp.Reverse(list1);
                tmp.Print(list1);
            }
            else
            {
                cout << "  " << endl;
            }
            break;

        case 7://表长
            cout << "当前两表长为:" << endl;
            cout << "表 1 :" << endl;
            tmp.Length(list);
            cout << "表 2 :" << endl;
            tmp.Length(list1);
            break;

        case 8://合并
            cout << "合并后链表为:" << endl;
            {Single_List* merge_list = tmp.Merge(list, list1);
            tmp.Print(merge_list);
            cout << endl; }
            break;

        default:
            system("cls");
            break;

        }

    }

    system("pause");
    return 0;
}

运行状况如下
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

<数据结构>创建一个单链表 的相关文章

随机推荐

  • 快速玩转 Llama2!阿里云机器学习 PAI 推出最佳实践

    前言 近期 Meta 宣布大语言模型 Llama2 开源 包含7B 13B 70B不同尺寸 分别对应70亿 130亿 700亿参数量 并在每个规格下都有专门适配对话场景的优化模型Llama 2 Chat Llama2 可免费用于研究场景和商
  • DesktopUI与ZeroTierOne的数据交互机制分析

    分析源码 梳理了一个调用关系图
  • 用python绘制RC低通滤波器bode图

    用python绘制RC低通滤波器bode图 Bode图 Bode图 国内有译作 伯德图 也有译作 波特图 是一种用于描述线性系统的频率响应的图形工具 频率响应是指系统对不同频率的输入信号的响应程度 通常用幅度和相位来表示 Bode图以对数坐
  • layui复选框按钮事件(智能去重刷新)

    1 写好复选框 lt input type checkbox value 0 name available title 智能去重 id available lay filter available gt 2 给复选框加事件 form on
  • RMSE数值在什么范围比较好呢

    RMSE Root Mean Squared Error 数值越小越好 通常来说 对于大多数应用来说 RMSE的值在0 1到1之间是可以接受的 当然 这取决于具体的应用和数据 如果数据本身具有很大的方差 那么RMSE的值就会更大
  • 如何制作静态和动态链接库-小白入门

    1 gcc编译过程 gcc为GNU编译套件 GNU Compiler Colletion 2 gcc编译命令 0 o 指定生成目标文件 00 O 设定优化级别 123越大越高 1 I 指定头文件目录 2 D 指定宏 避免修改源代码 3 g
  • 《我的世界》Python编程入门(9) 使用函数建造房子

    一 函数的基本概念 1 1 函数在数学中的概念 函数指一个量随着另一个量的变化而变化 函数的数学形式 y f x f是一种定义好的关系 可以简称为函数 在函数f中 只要x值的确定 那么y的值一定是确定的 y的值随x值的变化而变化 1 2 P
  • 设计模式(5)-适配器模式(Adapter Pattern)

    适配器模式 Adapter Pattern 顾名思义 就像变压器 转接头差不多 就像美国的生活电压是110V 中国是220V 就需要一个变压器将220V转换成110V 或者一个Type C接口想插如USB接口的东西 你就需要一个转换器 而这
  • [附源码]JSP+ssm计算机毕业设计小区疫情物资配送管理系统624kg【源码、数据库、LW、部署】

    项目运行 项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEcl
  • LeetCode题目笔记——2331. 计算布尔二叉树的值

    文章目录 题目描述 题目难度 简单 方法一 经典后序遍历 代码 C C Python 总结 题目描述 给你一棵 完整二叉树 的根 这棵树有以下特征 叶子节点 要么值为 0 要么值为 1 其中 0 表示 False 1 表示 True 非叶子
  • 【开源电机驱动】H 桥驱动-软件篇

    原文地址 http www modularcircuits com blog articles h bridge secrets h bridge control 本文为作者翻译校正稿件 含个人理解批注 H bridge Control H
  • 无需更改注册表 实现CHM文件从共享文件中直接打开

    直接上解决方法 无需更改注册表 将整个CHM文件压缩 在压缩文件中打开 chm文件 就可以正常显示相关内容 1 问题描述 压缩前 两台电脑 A是笔记本电脑 win10系统 B是台式电脑 win7系统 在A中设置了共享文件 并共享给了B CH
  • 别光看NB的Github开源项目,你得参考他们去设计自己的架构!

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 一 背景引入 首先简单介绍一下项目背景 公司对合作商家提供一个付费级产品 这个商业产品背后涉及到数百人的研发团队协作开发 包括各种业务系统来提供很多强大的业务功能 同
  • React 从零开始学习(四)—— 组件交互

    上一节 实现了把一个 prop 从父组件 Board 传递 给了子组件 Square 在 React 应用中 数据通过 props 的传递 从父组件流向子组件 这点跟 vue 是一样的 然后 跟着教程给组件添加交互功能 给组件添加交互功能
  • 简单学习识谱(六线谱)

    简单学习识谱 六线谱 参考资料 简谱的记谱方法 参考资料 吉他自学三月通 简谱的记谱方法 乐谱就是叙述音乐语言的文字 是每个学习音乐的人必须掌握的学习工具 当今世界通用的记谱法有五线谱和简谱 这两种方法都有着各自的特点 五线谱对于记录多声部
  • STM32通用定时器使用详解

    1 通用定时器基本介绍 通用定时器包括TIM2 TIM3 TIM4和TIM5 STM32通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成 每个定时器都是完全独立的 没有互相共享任何资源 它们可以一起同步操作 定时器可以进行定
  • main.c(31): warning: #223-D: function “uart_init“ declared implicitly

    Keil5编程之warning 223 D function xxx declared implicitly 1 函数没有头文件中进行声明 在头文件中添加声明 2 定义错误 字母大小可能不一致 仔细看一下出现问题的函数是否在声明和调用时使用
  • C语言入门——适合练手的密码本项目

    一 引言 学C语言有一段时间了 趁着正好做了密码本的小项目 把它分享出来 二 思路与原理 密码本 见名知意 就是存放账号密码 起到备忘录作用的本子 将需要备忘的数据通过加密存放在文本文件中 打开的文本文件为加密文本 需要通过软件查看已经存放
  • 用实际例子理解回调函数(Calback)

    用实际例子理解回调函数 Calback 在我们编码的过程中 调用和回调几乎无处不在 但是我对回调函数到底是怎样一回事并没有一个真正透彻的理解 最近我查找学习了一些资料 学到了很多 我参考了一些知乎上的分享 很不错 https www zhi
  • <数据结构>创建一个单链表

    单链表基本操作的实现 内容 构建线性表的链式存储结构 采用动态分配方式实现单链表的初始化 数据的插入 删除 输出单链表内中各元素 求单链表的长度 实现单链表中数据结点的按值排序 实现单链表的逆置 合并两个有序的单链表 有序的a表和有序的b表