数据结构上机练习——单链表的基本操作、头文件、类定义、main函数、多种链表算法的实现,含注释

文章目录

  • 单链表的基本操作实现
    • 1.头文件
    • 2.类定义和多种算法的实现
      • 2.1创建空表
      • 2.2头插法创建n个元素的线性链表
      • 2.3一个带头节点的链表存放一组整数,设计一个算法删除值等于x的所有节点。
      • 2.4计算线性表中值为偶数的节点个数
      • 2.5一个带头节点的单链表heada存放一组整数,设计分裂heada算法,偶数放在heada中,奇数放在headb中
    • 3.main函数和源码实现
      • 3.1测试实现:
      • 3.2LinkList.h
      • 3.3test.cpp

单链表的基本操作实现

1.头文件

  头文件和源文件分开有很多好处:可以提高编译速度、提高代码的可维护性、提高代码的可重用性和可扩展性,同时也可以使代码结构更清晰,方便代码的管理和维护。

LinkList.h

#pragma once#include<assert.h>//定义单链表节点
typedef struct LNode
{int data;LNode* next;}LNode;

test.cpp

#include<iostream>
using namespace std;#include"LinkList.h"

             

2.类定义和多种算法的实现

  (下面所有函数都默认在类中实现)

  我们以带头单向非循环链表为例:

  带头单向非循环链表是一种链表数据结构,其中每个节点包含一个数据域和一个指向下一个节点的指针域。在这种链表中,有一个特殊的节点称为头节点,它指向链表的第一个节点。头节点不是链表的一部分,仅用于方便操作。

在这里插入图片描述

             

2.1创建空表

  我们定义了一个名为LinkList的类,代表一个单链表。这个类有两个私有成员:一个指向LNode类型的指针_head,代表链表的头节点,以及一个整型变量_size,代表链表的大小。

//定义单链表类
class LinkList
{
public://默认构造函数LinkList(){_head = new LNode(0);//创建头结点(哨兵位节点)_size = 0;}private:LNode* _head;int _size;
};

             

2.2头插法创建n个元素的线性链表

  先以头插单个元素为例:

  我们可以先创建一个新的节点来存储该元素。然后,检查链表是否为空,如果为空,则新节点就是链表的第一个节点; 否则,新节点将插入到当前头节点的后面。插入完成后,_size(代表链表元素个数的变量)加1。

void push_front(const int& val)
{//创建一个插入的新节点,将要插入的值val赋值给它LNode* newnode = new LNode(val);LNode* cur = _head->next;//保存原来第一个结点//进行头插操作_head->next = newnode;_head->next->next = cur;//连接原来的第一个节点_size++;
}

  加上n循环即可实现头插法创建n个元素的线性链表

//头插法创建n个元素
void push_front_n()
{cout << "请输入要插入的元素个数:";int n;cin >> n;cout << endl;cout << "输入要插入的元素:";while (n){int tmp;cin >> tmp;push_front(tmp);n--;}
}

             

2.3一个带头节点的链表存放一组整数,设计一个算法删除值等于x的所有节点。

  无返回值版本

  我们先检查链表是否为空,如果为空,则输出一条错误消息并返回。如果链表非空,它开始遍历链表,检查每个节点的下一个节点是否为要删除的节点。如果是,则删除该节点并释放其内存;如果不是,则移动到下一个节点。 在遍历过程中,保持对当前节点的引用,以防止删除连续的要删除的节点时出现问题。

	//删除所有x的节点
void erase_all_x(int x)
{LNode* cur = _head;if (cur->next == nullptr)//判断是否为空链表{cout << "该链表为空不可删除\n";return;}else{while (cur && cur->next)//删除的数据有可能连续,所以最好保持当前节点{if (cur->next->data == x)//如果下一个节点为要删除节点{LNode* tmp = cur->next;//用临时指针保存要删除的节点cur->next = cur->next->next;//链表指向删除节点的下一个节点delete tmp;//删除节点中的元素tmp = nullptr;}else//如果下个节点不是删除节点,那直接指向下个节点{cur = cur->next;}}}
}

  有返回值版本

//删除所有x的节点,有删除节点返回true,无删除节点返回false
bool erase_all_x(int x)
{LNode* cur = _head;if (cur->next == nullptr){cout << "该链表为空不可删除\n";return false;}else{int count = 0;//设计一个计数器,统计是否有删除的节点while (cur && cur->next)//删除的数据有可能连续,所以最好保持当前节点{if (cur->next->data == x){count++;//有删除的节点,count++LNode* tmp = cur->next;cur->next = cur->next->next;//删除x节点delete tmp;tmp = nullptr;}else//如果下个节点不是删除节点,那直接指向下个节点{cur = cur->next;}}if (count == 0)//count==0,则没有可以删除的节点{cout << "链表中没有可以删除的元素" << endl;return false;}return true;}
}

             

2.4计算线性表中值为偶数的节点个数

  我们定义函数用于遍历链表并计算其中偶数节点的数量。首先,它检查链表是否为空,如果为空,则输出一条错误消息。如果链表非空,它开始遍历链表,检查每个节点的数据是否为偶数。如果是偶数,则计数器加1。 遍历完成后,输出链表中偶数节点的数量。

//打印链表中值为偶数的节点个数
void print_even_number()
{LNode* cur = _head->next;int count = 0;if (cur == nullptr){cout << "该链表为空,没有节点\n";}else//核心就在不断通过指针遍历寻找即可{while (cur)//遍历链表中的每一个节点{if (cur->data % 2 == 0){count++;//如果cur为偶数,计数++;}cur = cur->next;}cout << "该链表中偶数节点的个数为:" << count << endl;}
}

             

2.5一个带头节点的单链表heada存放一组整数,设计分裂heada算法,偶数放在heada中,奇数放在headb中

  我们定义该函数用于将链表中的偶数节点和奇数节点分开,使得偶数节点在heada链表中,奇数节点在headb链表中。

  函数使用两个指针cur1和cur2分别遍历heada和headb链表。在遍历过程中,如果当前节点的下一个节点是偶数节点,则保持原链表不变,移动cur1指针;

  如果当前节点的下一个节点是奇数节点,则将其从原链表中删除,并添加到headb链表的末尾,同时移动cur1和cur2指针。 最后,函数返回修改后的heada和headb链表。

//分裂链表,偶数在heada中,奇数在headb中
void divide_LinkList(LNode* heada, LNode* headb)
{LNode* cur1 = heada;LNode* cur2 = headb;while (cur1 && cur1->next)//退出循环的条件要cur1和cur1下个节点不为空{if (cur1->next->data % 2 == 0)//为偶数原链表不变{cur1 = cur1->next;//cur1直接向后移动}else//若链表为奇数,需要移动放入headb中{//交换链表节点操作LNode* tmp = cur1->next;cur1->next = cur1->next->next;//调整cur2,使其获得cur1的节点,断开cur1节点的后面节点的连接cur2->next = tmp;cur2->next->next = nullptr;//cur1和cur2各向后移动cur2 = cur2->next;}}
}

             

3.main函数和源码实现

3.1测试实现:

test_LinkList1();
在这里插入图片描述

test_LinkList2();
在这里插入图片描述

test_LinkList3();
在这里插入图片描述

             

3.2LinkList.h

#pragma once#include<assert.h>//定义单链表节点
typedef struct LNode
{int data;LNode* next;LNode(const int& val):data(val), next(nullptr){}}LNode;//定义单链表类
class LinkList
{
public://默认构造函数LinkList(){_head = new LNode(0);//创建头结点(哨兵位节点)_size = 0;}//拷贝构造函数 lt1(lt)LinkList(const LinkList& lt){LNode* oldcur = lt._head->next;//这个this指针是新建的链表lt1的this->_head = new LNode(0);this->_size = 0;LNode* newcur = _head;while (oldcur)//深拷贝以完成链表的赋值操作{//将旧链表中的值赋值到新链表中LNode* tmp = new LNode(oldcur->data);//向后移动新旧链表节点newcur->next = tmp;newcur = newcur->next;oldcur = oldcur->next;_size++;}}//析构函数~LinkList(){LNode* cur = _head->next;while (cur){LNode* tmp = cur;cur = cur->next;delete tmp;tmp = nullptr;}}//单链表打印void print(){LNode* cur = _head->next;if (cur == nullptr){cout << "该单链表为空\n";}else{cout << "该单链表中的元素为:";while (cur){printf("%d->", cur->data);cur = cur->next;}cout << "NULL\n";}}//单链表尾插void push_back(const int& val){LNode* newnode = new LNode(val);LNode* cur = _head;while (cur && cur->next)//找到尾结点{cur = cur->next;}cur->next = newnode;//尾插_size++;}//单链表头插void push_front(const int& val){LNode* newnode = new LNode(val);LNode* cur = _head->next;_head->next = newnode;_head->next->next = cur;_size++;}//单链表尾删void pop_back(){LNode* cur = _head->next;LNode* prev = _head;if (cur == nullptr){cout << "单链表为空不可删除\n";}else{while (cur && cur->next)//找到尾结点和前一个节点{cur = cur->next;prev = prev->next;}prev->next = nullptr;delete cur;cur = nullptr;_size--;}}//单链表头删void pop_front(){LNode* cur = _head->next;if (cur == nullptr){cout << "单链表为空不可删除\n";}else{_head->next = cur->next;delete cur;cur = nullptr;_size--;}}//头插法创建n个元素void push_front_n(){cout << "请输入要插入的元素个数:";int n;cin >> n;cout << endl;cout << "输入要插入的元素:";while (n){int tmp;cin >> tmp;push_front(tmp);//LNode* newnode = new LNode(tmp);//LNode* cur = _head->next;//if (cur == nullptr)//{//	_head->next = newnode;//}//else//{//	newnode->next = cur;//	_head->next = newnode;//}n--;//_size++;}}//删除第n个元素void erase(int n){assert(n > 0 && n <= _size);LNode* cur = _head;if (cur->next == nullptr){cout << "该链表为空不可删除\n";return;}else{LNode* tmp = cur;while (n)//找到删除节点的前一个位置{tmp = cur;cur = cur->next;n--;}tmp->next = tmp->next->next;delete cur;cur = nullptr;}}//单链表节点个数void print_size(){cout << "单链表节点个数为:" << _size << endl;}//删除所有x的节点,有删除节点返回true,无删除节点返回falsebool erase_all_x(int x){LNode* cur = _head;if (cur->next == nullptr){cout << "该链表为空不可删除\n";return false;}else{int count = 0;//设计一个计数器,统计是否有删除的节点while (cur && cur->next)//删除的数据有可能连续,所以最好保持当前节点{if (cur->next->data == x){count++;//有删除的节点,count++LNode* tmp = cur->next;cur->next = cur->next->next;//删除x节点delete tmp;tmp = nullptr;}else//如果下个节点不是删除节点,那直接指向下个节点{cur = cur->next;}}if (count == 0)//count==0,则没有可以删除的节点{cout << "链表中没有可以删除的元素" << endl;return false;}return true;}}//打印链表中值为偶数的节点个数void print_even_number(){LNode* cur = _head->next;int count = 0;if (cur == nullptr){cout << "该链表为空,没有节点\n";}else{while (cur)//遍历链表中的每一个节点{if (cur->data % 2 == 0){count++;//如果cur为偶数,计数++;}cur = cur->next;}cout << "该链表中偶数节点的个数为:" << count << endl;}}//返回当前链表的头结点LNode* get_head(){return _head;}//分裂链表,偶数在heada中,奇数在headb中void divide_LinkList(LNode* heada, LNode* headb){LNode* cur1 = heada;LNode* cur2 = headb;while (cur1 && cur1->next){if (cur1->next->data % 2 == 0)//为偶数原链表不变{cur1 = cur1->next;}else//若链表为奇数,需要移动放入headb中{//交换链表节点操作LNode* tmp = cur1->next;cur1->next = cur1->next->next;cur2->next = tmp;cur2->next->next = nullptr;//cur1和cur2各向后移动cur2 = cur2->next;}}}private:LNode* _head;int _size;
};

             

3.3test.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
using namespace std;#include"LinkList.h"void test_LinkList1()
{LinkList lt;//链表打印lt.print();//测试空链表删除lt.pop_front();//尾插lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.print();//头插lt.push_front(5);lt.push_front(6);lt.push_front(7);lt.push_front(8);lt.print();//打印链表节点lt.print_size();//尾删lt.pop_back();lt.pop_back();lt.print();//头删lt.pop_front();lt.pop_front();lt.print();lt.print_size();
}void test_LinkList2()
{//头插法创建n个元素的链表LinkList lt;lt.push_front_n();lt.print();lt.print_size();
}void test_LinkList3()
{LinkList lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);lt.push_back(6);lt.push_back(7);lt.push_back(8);lt.push_back(9);lt.push_back(10);lt.print();lt.print_size();lt.push_back(6);lt.push_back(6);lt.push_back(6);//删除第11节点的元素lt.erase(11);lt.print();//删除所有元素为6的节点cout << "是否删除成功:" << lt.erase_all_x(6) << endl;lt.print();cout << "是否删除成功:" << lt.erase_all_x(6) << endl;lt.print();//打印所有节点为偶数的个数lt.print_even_number();//拷贝构造函数LinkList lt1(lt);lt1.print();lt1.print_size();//编译器生成了默认的赋值运算符重载LinkList lt2 = lt1;lt2.print();//创建空链表LinkList lt3;lt3.print();lt1.push_back(11);lt1.push_back(14);lt1.push_back(12);lt1.push_back(13);lt1.print();//分离链表lt1,使lt1只含有偶数,lt3只含有奇数lt1.divide_LinkList(lt1.get_head(), lt3.get_head());lt1.print();lt3.print();
}int main()
{//不想输入数据就调用test_LinkList1()或test_LinkList3();//test_LinkList1();//test_LinkList2();test_LinkList3();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx实现反向代理实例

1 前言 1.1 演示内容 在服务器上访问nginx端口然后跳转到tomcat服务器 1.2 前提条件 前提条件&#xff1a;利用docker安装好nginx、tomcat、jdk8&#xff08;tomcat运行需要jdk环境&#xff09; 只演示docker安装tomcat&#xff1a; 默认拉取最新版tomcat docker pull t…

Qt地铁智慧换乘系统浅学( 三 )最少路径和最少换乘实现

本算法全都基于广度优先 概念最短路径实现所用容器算法思路 最少换乘实现所需容器算法思路 成果展示代码实现判断是最短路径还是最少换乘最短路径代码实现最少换乘代码实现根据所得List画出线路 ui界面的维护&#xff08;前提条件&#xff09;界面初始化combox控件建立槽函数 概…

84、Redis客户端-->可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用

Redis客户端–>可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用 ★ Redis客户端&#xff1a; ▲ Redis自带的命令行工具&#xff08;简陋&#xff09;&#xff1a; CLI工具&#xff0c;重新打开一个命令行窗口&#xff0c;在其中输入如下命令&…

人工智能轨道交通行业周刊-第61期(2023.9.18-9.24)

本期关键词&#xff1a;焊线机器人、智能综合运维管理系统、信号平面图、铁路部门架构、书生浦语大模型 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通…

uniapp、vue实现滑动拼图验证码

uniapp、vue实现滑动拼图验证码 实际开发工作中&#xff0c;在登陆的时候需要短信验证码&#xff0c;但容易引起爬虫行为&#xff0c;需要用到反爬虫验证码&#xff0c;今天介绍一下拼图验证码&#xff0c;解决验证码反爬虫中的滑动验证码反爬虫。滑动拼图验证码是在滑块验证码…

Android应用线上闪退问题解决

解决Android应用线上闪退问题需要仔细的监控、调试和分析。以下是一些解决Android线上闪退问题的工具和方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 工具&#xff1a; 1.Google Play 控制台&…

Mysql安装

一、Mysql官网下载安装 MySQL :: Download MySQL Community Server下载 二、安装 下载后打开文件进行安装&#xff1a; 选择custom自定义 选择后带点击Execute 接着下一步 设置密码&#xff0c;下一步 全好后点击finish 之后继续下一步&#xff0c;finish

怎样防止员工泄露技术?(十条避免公司泄密的措施)

在当今信息化社会&#xff0c;公司信息的安全性和保密性显得尤为重要。一旦公司信息泄露&#xff0c;不仅会对公司的经营造成严重影响&#xff0c;还可能引发法律纠纷。因此&#xff0c;采取有效的措施来防止公司信息泄露是非常必要的。以下是一些具体的措施&#xff1a; 部署洞…

数据结构之【泛型】

泛型&#xff1a;定义阶段不明确具体类型&#xff0c;产生对象时明确具体类型。 //Object是Java中的最高参数统一化&#xff0c;能够接受所有的引用类型&#xff1b; //有了包装类的自动拆装箱之后&#xff0c;Object还能够接收基本类型数值&#xff08;自动装箱&#xff09; …

入门级制作电子期刊的网站推荐

随着数字化时代的到来&#xff0c;越来越多的人开始尝试制作自己的电子期刊。如果你也是其中的一员&#xff0c;那么这篇文章可以帮助你制作电子期刊。无论是初学者还是有一定经验的制作者&#xff0c;都能快速完成高质量的电子期刊制作 小编经常使用的工具是-----FLBOOK在线制…

修改vscode底部栏背景和字体颜色

修改vscode底部栏背景和字体颜色 如图&#xff1a; 首先打开齿轮&#xff0c;打开设置搜索workbench.colorCustomizations,然后点击编辑setting.json修改setting.json内内容 "workbench.colorCustomizations": {"statusBar.foreground": "#FFFFFF…

【C++】C++的类型转换

C的类型转换 一、C语言中的类型转换二、C的类型转换1、static_cast2、reinterpret_cast3、const_cast4、dynamic_cast 三、RTTI 一、C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与…

【力扣每日一题】2023.9.23 树上的操作

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这是一道程序设计类的题目&#xff0c;题目比较长&#xff0c;我稍微概括一下。 构造函数中给我们一个数组&#xff0c;第i个元素表示第…

3D目标检测实战 | 图解KITTI数据集与数据格式

目录 1 数据集简介2 传感器坐标系3 数据集下载与组织4 数据内容说明4.1 矫正文件calib4.2 图像文件image4.3 点云文件velodyne4.4 标签文件label4.5 平面文件plane 1 数据集简介 KITTI数据集是一个广泛应用于自动驾驶和计算机视觉领域的公开数据集。该数据集由德国卡尔斯鲁厄理…

牛客java训练题 day1

9.24 day1 Q 1. this 指针是用来干什么的&#xff1f; 2.基类和派生类分别是指什么&#xff1f; 3.为什么方法中不能写静态变量 4. 解释一下ASCII码和ANSI码和两者的区别 5.简述j ava.io java.sql java.awt java.rmi 分别是什么类型的包 6. 看下面一段代码&#xff1a;…

Ubuntu安装RabbitMQ server - 在外远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

安装OpenSearch

title: “安装opensearch” createTime: 2021-11-30T19:13:4508:00 updateTime: 2021-11-30T19:13:4508:00 draft: false author: “name” tags: [“es”,“安装”] categories: [“OpenSearch”] description: “测试的” 说明 基于Elasticsearch7.10.2 的 opensearch-1.1.…

使用QLoRA对Llama 2进行微调的详细笔记

使用QLoRA对Llama 2进行微调是我们常用的一个方法&#xff0c;但是在微调时会遇到各种各样的问题&#xff0c;所以在本文中&#xff0c;将尝试以详细注释的方式给出一些常见问题的答案。这些问题是特定于代码的&#xff0c;大多数注释都是针对所涉及的开源库以及所使用的方法和…

【工作记录】springboot集成aop实现日志@20230918

springboot集成aop实现日志 1. 添加依赖 <!-- aop 依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>2. 定义注解 Target(ElementType.METHOD)…

windows 安装 MySQL 绿色版

windows 安装 MySQL 绿色版 下载 官网&#xff1a; MySQL下载页面&#xff1a; MySQL直接下载链接&#xff1a;https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.34-winx64.zip 安装 将下载的mysql.zip文件解压缩到指定目录 搜索 cmd 并以管理员身份运行 切换到…