【C++】单链表——单链表的基本操作

1、单链表的定义

 由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,不需要使用地址连续的存储单元,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。

单链表的特点:

  • 单链表不要求逻辑上相邻的两个元素在物理位置上也相邻,因此不需要连续的存储空间
  • 单链表是非随机的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。

优点:

  • 支持动态内存分配。由于单链表不需要预先分配一段连续的空间,因此可以根据实际需求动态地申请、释放节点空间,避免浪费内存。
  • 支持高效的插入、删除操作。由于单链表中的节点是通过指针相连的,因此在插入、删除一个节点时,只需要修改其前驱节点或后继节点的指针即可,时间复杂度为O ( 1 ) 。
     

 缺点:

  • 不支持随机访问。由于单链表中的节点不是连续存储的,因此不能像数组一样通过下标来直接访问一个元素,需要从头节点开始遍历整个链表才能访问任意位置的元素。

 创建一个类

template <class T>								// T为单链表存储的元素类型
class linkList
{
private:struct Node{public:T  data;								  // 结点的数据域 Node* next;								  // 结点的指针域,指向后继结点 Node(const T value, Node* p = NULL)       // 具有两个参数的Node构造函数 {	data = value;next = p;}Node(Node* p = NULL)                      // 具有一个参数的Node构造函数  { 						next = p;}};Node* head;								// 单链表的头指针 Node* tail;    							// 单链表的尾int curLength;							// 单链表的当前长度Node* getPosition(int i)const;			// 返回指向单链表中第i个元素的指针     public:linkList();								    // 构造函数 ~linkList();								// 析构函数  void clear(); 								// 将单链表清空,使之成为空表bool empty()const;                          // 判空int size();                                 // 返回单链表的当前实际长度  						 void insert(int i, const T& value);	        // 在位置i上插入一个元素value,表的长度增1void remove(int i);							// 删除位置i上的元素value,若删除位置合法,表的长度减1 int search(const T& value)const;		    // 查找值为value的元素第一次出现的位序T visit(int i)const;					    // 访问位序为i的元素值,“位序”0表示第一个元素,类似于数组下标void traverse()const;						// 遍历单链表	void headCreate();							// “头插法”void tailCreate();							// “尾插法”void inverse();								// 逆置单链表int prior(const T& value)const;		        // 查找值为value的元素的前驱};

 2、单链表的初始化

  • 通常会用头指针来标识一个单链表,头指针为nullptr时表示一个空表。
  • 但是,为了操作方便,会在单链表的第一个结点之前附加一个结点,称为头结点
  • 头结点的数据域可以不设任何信息,也可以记录表长等信息。

 

代码实现: 

template <class T>
linkList<T>::linkList()
{head = tail = new Node();				    // 创建带有头结点的空表curLength = 0;
}

 3、单链表的建立

3.1、头插法建立单链表

头插法建立单链表是说将新结点插入到当前链表的表头,即头结点之后。

思路:输入一个结束标志flag,使用一个while循环,判断条件是 value != flag

代码实现:

template <class T>  						// 头插法创建 
void linkList<T>::headCreate()
{Node* p;T value, flag;cin >> flag;									// 输入结束标志cin >> value;while (value != flag){p = new Node(value);p->next = head->next;head->next = p;curLength++;cin >> value;}
}

3.2、尾插法建立单链表

尾插法建立单链表,就是将新结点插入到当前链表的表尾。

代码实现:

template <class T>  						// 尾插法创建链表
void linkList<T> ::tailCreate()
{Node* p;T value, flag;cin >> flag;									// 输入结束标志cin >> value;while (value != flag){p = new Node(value);tail->next = p;tail = p;curLength++;cin >> value;}}

4、单链表的遍历 

代码实现:

template <class T>
void  linkList<T> ::traverse()const
{Node* p = head->next;while (p != nullptr){cout << p->data << "  ";p = p->next;}cout << endl;}

5、单链表的长度

代码实现:

template <class T>
int linkList<T>::size()
{ return curLength; 
}

6、单链表的查找

6.1、按值查找

代码实现:

template <class T>
int linkList<T> ::search(const T& value)const
{Node* current = head->next;int i = 0;while (current != nullptr){if (current->data == value){break;}else{current = current->next;i++;}}if (current != nullptr){return i;}return -1;}

6.2、按位查找

代码实现:

template <class T>  						// 访问位序为i的元素返回其数据域
T linkList<T> ::visit(int i)const 
{if (i < 0 || i>(curLength - 1)){T a = 0;return a;}Node* current = head->next;while (i--){current = current->next;}return current->data;}

7、单链表的插入

返回指向单链表中第i个元素的指针

template <class T>
typename linkList<T> ::Node* linkList<T> ::getPosition(int i)const
{Node* ptemp = head;int k = 0;while (k < i){ptemp = ptemp->next;k++;}return ptemp;
}

代码实现:

template  <class T>
void linkList<T> ::insert(int i, const T& value)
{Node* current = getPosition(i);Node* newNode = new Node(value);newNode->next = current->next;current->next = newNode;curLength++;}

8、单链表的删除

代码实现:

template  <class T>
void  linkList<T>::remove(int i)
{Node* current = getPosition(i);Node* del = current->next;current->next = del->next;delete del;curLength--;}

9、单链表的判空

代码实现:

template <class T>
bool linkList<T>::empty()const
{return head->next == nullptr;
}

总代码实现:

#include<stack>template <class T>								// T为单链表存储的元素类型
class linkList
{
private:struct Node{public:T  data;								  // 结点的数据域 Node* next;								  // 结点的指针域,指向后继结点 Node(const T value, Node* p = NULL)       // 具有两个参数的Node构造函数 {	data = value;next = p;}Node(Node* p = NULL)                      // 具有一个参数的Node构造函数  { 						next = p;}};Node* head;								// 单链表的头指针 Node* tail;    							// 单链表的尾int curLength;							// 单链表的当前长度Node* getPosition(int i)const;			// 返回指向单链表中第i个元素的指针     public:linkList();								    // 构造函数 ~linkList();								// 析构函数  void clear(); 								// 将单链表清空,使之成为空表bool empty()const;                          // 判空int size();                                 // 返回单链表的当前实际长度  						 void insert(int i, const T& value);	        // 在位置i上插入一个元素value,表的长度增1void remove(int i);							// 删除位置i上的元素value,若删除位置合法,表的长度减1 int search(const T& value)const;		    // 查找值为value的元素第一次出现的位序T visit(int i)const;					    // 访问位序为i的元素值,“位序”0表示第一个元素,类似于数组下标void traverse()const;						// 遍历单链表	void headCreate();							// “头插法”void tailCreate();							// “尾插法”void inverse();								// 逆置单链表int prior(const T& value)const;		        // 查找值为value的元素的前驱};template <class T>
linkList<T>::linkList()
{head = tail = new Node();				    // 创建带有头结点的空表curLength = 0;
}template <class T>
linkList<T>::~linkList()
{clear();delete head;								// 删除头结点
}template <class T>
bool linkList<T>::empty()const
{return head->next == nullptr;
}template <class T>
int linkList<T>::size()
{ return curLength; 
}template <class T>
void linkList<T>::clear()
{Node* p = head->next;while (p){head = head->next;delete p;p = head;}}template <class T>
typename linkList<T> ::Node* linkList<T> ::getPosition(int i)const
{Node* ptemp = head;int k = 0;while (k < i){ptemp = ptemp->next;k++;}return ptemp;
}template  <class T>
void linkList<T> ::insert(int i, const T& value)
{Node* current = getPosition(i);Node* newNode = new Node(value);newNode->next = current->next;current->next = newNode;curLength++;}template  <class T>
void  linkList<T>::remove(int i)
{Node* current = getPosition(i);Node* del = current->next;current->next = del->next;delete del;curLength--;}template <class T>
void  linkList<T> ::traverse()const
{Node* p = head->next;while (p != nullptr){cout << p->data << "  ";p = p->next;}cout << endl;}template <class T>
int linkList<T> ::search(const T& value)const
{Node* current = head->next;int i = 0;while (current != nullptr){if (current->data == value){break;}else{current = current->next;i++;}}if (current != nullptr){return i;}return -1;}template <class T>  						// 访问位序为i的元素返回其数据域
T linkList<T> ::visit(int i)const 
{if (i < 0 || i>(curLength - 1)){T a = 0;return a;}Node* current = head->next;while (i--){current = current->next;}return current->data;}template <class T>  						// 头插法创建 
void linkList<T>::headCreate()
{Node* p;T value, flag;cin >> flag;									// 输入结束标志cin >> value;while (value != flag){p = new Node(value);p->next = head->next;head->next = p;curLength++;cin >> value;}
}template <class T>  						// 尾插法创建链表
void linkList<T> ::tailCreate()
{Node* p;T value, flag;cin >> flag;									// 输入结束标志cin >> value;while (value != flag){p = new Node(value);tail->next = p;tail = p;curLength++;cin >> value;}}
template <class T>  						// 头插法逆置   
void linkList<T> ::inverse()
{Node* temp = nullptr;Node* p = head->next;head->next = nullptr;while (p != nullptr){temp = p;p = p->next;temp->next = head->next;head->next = temp;}}template <class T>
int linkList<T> ::prior(const T& value)const
{Node* current = head->next;int a = 0;Node* p = nullptr;while (current != nullptr){if (current->data == value){break;}else{current = current->next;a++;}}if (current != nullptr){return a - 1;}return -1;}

执行

#include<iostream>
using namespace std;#include"SList.h"int main()
{linkList<int>* lk1, * lk2;lk1 = new linkList<int>();lk2 = new linkList<int>();int i;int val;lk1->headCreate();          // 测试头插法创建单链表lk2->tailCreate();          // 测试尾插法创建单链表 lk1->traverse();           // 测试遍历lk2->traverse();           // 测试遍历cout << "查找值为2的位序:" << lk1->search(2) << endl;cout << "查找位序为2的值" << lk1->visit(2) << endl;cout << "长度:" << lk1->size();return 0;
}

执行结果

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

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

相关文章

运维知识点-openResty

openResty 企业级实战——畅购商城SpringCloud-网站首页高可用解决方案-openRestynginxlua——实现广告缓存测试企业级实战——畅购商城SpringCloud-网站首页高可用解决方案-openRestynginxlua——OpenResty 企业级实战——畅购商城SpringCloud-网站首页高可用解决方案-openRes…

基于深度学习的表情动作单元识别综述

论文标题&#xff1a;基于深度学习的表情动作单元识别综述 作者&#xff1a;邵志文1&#xff0c;2&#xff0c;周 勇1&#xff0c;2&#xff0c;谭 鑫3&#xff0c;马利庄3&#xff0c;4&#xff0c;刘 兵1&#xff0c;2&#xff0c;姚 睿1&#xff0c;2 发表日期&#xff1a…

idea不需安装插件,自动生成mybatis-plus对应的实体类entity,带注解@TableName、@TableId、@TableField

目录 1、修改Generate poJOs.groovy文件 2、idea中连接数据库 3、生成entity代码 4、查看生成的实体类 1、修改Generate poJOs.groovy文件 在项目下方点击Scratches and Consoles→ Extensions→ Database Tools and SQL箭头→schema→ Generate POJOs.groovy 替换为以下文…

504. 七进制数

这篇文章会收录到 : 算法通关第十三关-青铜挑战数学基础问题-CSDN博客 七进制数 描述 : 给定一个整数 num&#xff0c;将其转化为 7 进制&#xff0c;并以字符串形式输出。 题目 : LeetCode 504. 七进制数 : 504. 七进制数 分析 : 我们先通过二进制想一下7进制数的变化特…

爬虫代理技术与构建本地代理池的实践

爬虫中代理的使用&#xff1a; 什么是代理 代理服务器 代理服务器的作用 就是用来转发请求和响应 在爬虫中为何需要使用代理&#xff1f; 隐藏真实IP地址&#xff1a;当进行爬取时&#xff0c;爬虫程序会发送大量的请求到目标网站。如果每个请求都使用相同的IP地址&#xff…

HotSpot 虚拟机中的对象

1、对象的创建 Java 是一门面向对象的编程语言&#xff0c;程序运行过程中无时无刻都有对象被创建出来。在语言层面上&#xff0c;创建对象通常仅仅是一个 new 关键字&#xff0c;而虚拟机中&#xff0c;对象&#xff08;仅限于普通 Java 对象&#xff0c;不包括数组和 Class …

手写VUE后台管理系统5 - 整合状态管理组件pinia

整合状态管理组件 安装整合创建实例挂载使用 pinia 是一个拥有组合式 API 的 Vue 状态管理库。 pinia 官方文档&#xff1a;https://pinia.vuejs.org/zh/introduction.html 安装 yarn add pinia整合 所有与状态相关的文件都放置于项目 src/store 目录下&#xff0c;方便管理 在…

基于卷积神经网络的人体行为识别系统开发与设计

摘 要 基于卷积神经网络的人体行为识别的开发与设计 摘要&#xff1a;随着计算机领域不断的创新、其它行业对计算机的应用需求的提高以及社会对解放劳动力的迫切&#xff0c;人机交互成为人们关注的问题。深度学习的出现帮助了人们实现人机交互&#xff0c;而卷积神经网络是其…

自动化测试框架搭建步骤教程

说起自动化测试&#xff0c;我想大家都会有个疑问&#xff0c;要不要做自动化测试&#xff1f; 自动化测试给我们带来的收益是否会超出在建设时所投入的成本&#xff0c;这个嘛别说是我&#xff0c;即便是高手也很难回答&#xff0c;自动化测试的初衷是美好的&#xff0c;而测试…

福德植保无人机:农业科技的新篇章

一、引言随着科技的不断发展&#xff0c;无人机技术在许多领域中都得到了广泛的应用。近年来&#xff0c;福德植保无人机在农业领域大放异彩&#xff0c;成为了现代化农业的重要一环。本篇文章将为您详细介绍福德植保无人机的优势、特点以及未来发展趋势。 二、福德植保无人机的…

Spring Cloud Gateway集成SpringDoc,集中管理微服务API

本文目标 Spring Cloud微服务集成SpringDoc&#xff0c;在Spring Cloud Gateway中统一管理微服务的API&#xff0c;微服务上下线时自动刷新SwaggerUi中的group组。 依赖版本 框架版本Spring Boot3.1.5Spring Cloud2022.0.4Spring Cloud Alibaba2022.0.0.0Spring Doc2.2.0Nac…

CDC with Async FIFO

https://zipcpu.com/blog/2018/07/06/afifo.html