单链表---结构体实现

定义

链表称为线性表的链式存储,顺序表逻辑上相邻的数据,存储位置也相邻。链表逻辑上相邻的数据,存储位置是随机分布在内存的各个位置上的。

对于每一个结点,定义的结构体是:

typedef struct _LinkNode 
{int date;				//数据域,存储数据,这里是int类型的数据struct _LinkNode* next; // 指针域,指向了后继元素(下一个结点)的地址
}LinkNode , LinkList;       //两个别名的作用是一模一样的,只是为了区分头结点和结点

 链表的初始化

我们用一个结构体指针L来指向链表,最开始是带一个头结点的空链表,头结点的数据域一般赋值为-1,也可以存储着链表的长度。头结点的指针域指针第一个元素结点,最开始是没有元素结点的空链表(有头结点),如图:

代码实现

bool initLinkList(LinkList*& L) //参数是对结构体指针的引用
{L = new LinkList; //也可以写成 L = new LinkNode ;if (!L){return false; // 申请内存失败,返回了一个空指针}L->next = NULL;return true;
}

链表的插入

头插法

将新结点插到头结点的后面,有两种形式,一是链表为空,二是链表中已有元素结点,如图

你可以分情况,不过也可以不用,例如:

bool insertLinkList(LinkList*& L, LinkNode *node) //node指向要添加的结点
{if (!L || !node) return false;node->next = L->next; //包含两种情况L->next = node;return true;
}

尾插法

尾插,顾名思义就是在最后一个结点插入之后,也分两种情况,一是链表为空,二是链表中已有元素结点,第一种情况的图和头插法的第一种情况的图一样,就是插入方式不同,以下是第二种情况的图:

我们只需要找到 next 指向 NULL 的这个结点就好了

bool LinkListinsert(LinkList*& L, LinkNode *node)
{if (!L || !node) return false;LinkNode* p = NULL;p = L;while (p->next != NULL) //如果是空链表,p == L,所以是包含两种情况{p = p->next;}node->next = p->next;p->next = node;return true;
}

指定位置插入

在第 i 个结点前插入,那么我们就必须有个临时指针指向第 i-1 个结点

bool InsertLink(LinkList*& L, int i, int e) // 这里也可以用之前的LinkNode *node参数,不过可能i不合法
{if (!L) return false;LinkNode* p = L , *s = NULL ;int j = 0;while (p && j < i - 1) // 指向第 i-1 个结点{	p = p->next;j++;}//如果在第0个位置之前插入(i<1) || 如果在最后一个结点+2的位置之前插入(i>n+1,n为链表长度)---都是非法的if (i < 1 || !p) return false;s = new LinkNode;s->date = e;s->next = p->next;p->next = s;return true;
}

遍历链表(打印链表)

bool PrintLinkList(LinkList *& L)
{if(!L) return false; LinkNode* p = L->next; //首先指向第一个结点,如果为空链表就会指向 NULLwhile (p != NULL) // 直到指向最后一个结点的 next 指针(NULL){printf("%d ", p->date);p = p->next;}cout << endl;return true;
}

遍历链表,也可以用来求链表的长度,代码与这个类似。

链表的获取

获取链表第 i 个结点的数据域。

bool GetElemLink(LinkList*& L, int i, int &e) //e返回获取的数据域
{LinkNode* p = L;int j = 0;while ( p!=NULL && j < i){p = p->next;j++;}if (p==NULL || i < 1) //i是非法的:i > n(n为链表长度,例如:获取第n+1个结点的数据域)或者是 i < 1(例如:获取了第0个结点的数据域){return false;}e = p->date;return true;
}

链表的查找

查找我们输入的元素在链表中出现的第一个位置。

bool FindElem(LinkList* L, int e,int &index) // index返回位置
{if (!L || !L->next) return false; //空链表LinkNode* p = L->next; // 现在指向第一个结点int j = 1;  while (p != NULL && p->date != e) {p = p->next;j++;}if (p == NULL)return false;else{index = j;return true;}
}

链表的删除

删除第 i 个结点,i 可能不合法,注意不合法的原因。

bool DeleteLinkNode(LinkList*& L, int i)
{LinkNode* p = NULL , *q = NULL;p = L;int j = 0;while ( p->next!=NULL && j < i - 1){p = p->next;j++;}// 指向第 i-1 个结点if (i < 1 || p->next == NULL) //i非法,删除第0个结点(i<1) 或者是 删除第n+1个结点(i>n,n为链表的长度)return false;else{q = p->next;p->next = q->next ;delete q;return true;}}

链表的销毁(清空)

销毁就是要归还所申请的内存,删除某个结点时,一定要保存下一个结点的地址。简要解释:先保存第一个结点的地址,随后删除头结点(也申请了空间),再保存第二个结点的地址,删除第一个结点,再保存第三个结点……以此类推,可以将全部结点删除。

void DestoryLink(LinkList*& L)
{LinkNode* p = NULL, * q = NULL;p = L;while (p != NULL){	q = p->next;//cout << "删除元素" << p->date << endl;delete p;p = q;}}

总代码

以下是全部代码,链表的函数有不同的实现方法。也许我的代码和别人有些差异,所以可以看看 main 函数中是怎样的。

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>using namespace std;typedef struct _LinkNode
{int date;				//数据域struct _LinkNode* next; // 指针域}LinkNode , LinkList;//初始化链表
bool initLinkList(LinkList*& L)
{L = new LinkList;if (!L){return false;}L->next = NULL;return true;
}//前插法
bool insertLinkList(LinkList*& L, LinkNode *node)
{if (!L || !node) return false;node->next = L->next;L->next = node;return true;
}//尾插法
bool LinkListinsert(LinkList*& L, LinkNode *node)
{if (!L || !node) return false;LinkNode* p = NULL;p = L;while (p->next != NULL){p = p->next;}node->next = p->next;p->next = node;return true;
}//在第i个结点前插入---指定位置插入
bool InsertLink(LinkList*& L, int i, int e)
{if (!L) return false;LinkNode* p = L , *s = NULL ;int j = 0;while (p && j < i - 1){	p = p->next;j++;}//如果在第0个位置之前插入(i<1) || 如果在最后一个结点+2的位置之前插入(i>n+1,n为链表长度)---都是非法的if (i < 1 || !p) return false;s = new LinkNode;s->date = e;s->next = p->next;p->next = s;return true;
}//打印链表
void PrintLinkList(LinkList *& L)
{LinkNode* p = L->next;while (p != NULL){printf("%d ", p->date);p = p->next;}cout << endl;
}//获取第i个结点的数据元素
bool GetElemLink(LinkList*& L, int i, int &e)
{LinkNode* p = L;int j = 0;while ( p!=NULL && j < i){p = p->next;j++;}if (p==NULL || i < 1){return false;}e = p->date;return true;
}//在链表中查找元素,并且用index返回位置
bool FindElem(LinkList* L, int e,int &index)
{if (!L || !L->next) return false;LinkNode* p = L->next;int j = 1;while (p && p->date != e){p = p->next;j++;}if (p == NULL)return false;else{index = j;return true;}
}//删除第i个结点
bool DeleteLinkNode(LinkList*& L, int i)
{LinkNode* p = NULL , *q = NULL;p = L;int j = 0;while ( p->next!=NULL && j < i - 1){p = p->next;j++;}if (i < 1 || p->next == NULL) //删除第0个结点(i<1) 或者是 删除第n+1个结点(i>n,n为链表的长度)return false;else{q = p->next;p->next = q->next ;delete q;return true;}}//清空(销毁)链表
void DestoryLink(LinkList*& L)
{LinkNode* p = NULL, * q = NULL;p = L;while (p != NULL){	q = p->next;//cout << "删除元素" << p->date << endl;delete p;p = q;}}
int main(void)
{LinkList* L = NULL; //指向表头(头结点)的指针LinkNode* e = NULL; //指向结点的指针initLinkList(L);int elem = 0;		//结点的数据元素int i;				//第几个结点int n = 0;			//输入的个数int flag = -1;while (flag != 0){cout << "1.前插链表" << endl<< "2.尾插链表" << endl<< "3.指定位置前插入" << endl<< "4.打印链表" << endl<< "5.获取第i个结点的数据" << endl<< "6.查找元素" << endl<<"7.删除元素"<<endl<< "0.退出(销毁链表)" << endl;cout << "请选择:";cin >> flag;switch (flag){case 1:cout << "请输入前插法插入链表的个数";cin >> n;cout << "请依次输入" << n << "个数:";while (n--){e = new LinkNode;cin >> e->date;insertLinkList(L, e);}break;case 2:cout << "请输入尾插入链表的个数";cin >> n;cout << "请依次输入" << n << "个数:";while (n--){e = new LinkNode;cin >> e->date;LinkListinsert(L, e);}break;case 3:cout << "请输入插入的位置和元素:";cin >> i >> elem;InsertLink(L, i, elem);break;case 4:PrintLinkList(L);break;case 5:cout << "请输入要获取的结点i:";cin >> i;if (GetElemLink(L, i, elem)){cout << "第" << i << "个结点的值为" << elem << endl;}else{cout << "获取元素失败" << endl;}break;case 6:cout << "请输入要查找的元素:";cin >> elem;if (FindElem(L, elem, i)){cout << "找到了,此元素的位置是" << i << endl;}else{cout << "表中无此值" << endl;}break;case 7:cout << "请输入要删除的结点i:";cin >> i;if (DeleteLinkNode(L, i)){cout << "删除成功" << endl;}else{cout << "删除失败" << endl;}break;case 0:DestoryLink(L);break;default:cout << "输入非法! " << endl;break;}}return 0;
}

这里也可以将代码复制,自己调试测试一下,删除某些代码,看看会有什么影响,更能理解。

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

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

相关文章

Java-使用sqlSessionTemplate实现批量更新-模拟mybatis 动态sql

环境准备&#xff08;非核心方法&#xff09; 创建表 创建表的sql(下表是基于Oracle创建的) CREATE TABLE "SYSTEM"."STUDENT" ("ID" NUMBER(10, 0),"NAME" VARCHAR2(20 BYTE),"ADDRES" CLOB,PRIMARY KEY ( …

milvus和相似度检索

流程 milvus的使用流程是 创建collection -> 创建partition -> 创建索引(如果需要检索) -> 插入数据 -> 检索 这里以Python为例, 使用的milvus版本为2.3.x 首先按照库&#xff0c; python3 -m pip install pymilvus Connect from pymilvus import connections c…

mac电脑版数字图像处理软件:ACDSee Photo Studio 9最新 for Mac

ACDSee Photo Studio 9是一款由ACD Systems开发的功能强大的照片管理和编辑软件&#xff0c;专为Mac用户提供一站式解决方案&#xff0c;方便用户轻松浏览、管理和编辑照片。该软件提供了许多实用的工具和功能&#xff0c;包括高效的导入和排序工具、强大的编辑工具、智能组织和…

CustomTabBar 自定义选项卡视图

1. 用到的技术点 1) Generics 泛型 2) ViewBuilder 视图构造器 3) PreferenceKey 偏好设置 4) MatchedGeometryEffect 几何效果 2. 创建枚举选项卡项散列&#xff0c;TabBarItem.swift import Foundation import SwiftUI//struct TabBarItem: Hashable{ // let ico…

Java练习题-获取数组元素最大值

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;Java练习题 &#x1f4ac;个人格言&#xff1a;不断的翻越一座又…

Qt之给控件添加右键菜单

一、设置控件 在对应控件的属性中&#xff0c;将contextMenuPolicy设置为CustomContextMenu。 二、添加槽函数 在对应控件上右键选择槽函数customContextMenuRequested(QPoint)。 三、在槽函数中添加右键菜单 在槽函数中输入如下代码&#xff0c;添加右键菜单。 //右键菜单 …

Flutter 剪裁(Clip)

&#x1f525; ClipOval &#x1f525; 子组件为正方形时剪裁成内贴圆形&#xff1b;为矩形时&#xff0c;剪裁成内贴椭圆 裁剪纯色背景 ClipOval(child: Container(width: 300.w,height: 300.w,decoration: const BoxDecoration(color: Colors.red),),), 裁剪背景图片 裁剪前…

《Deep Residual Learning for Image Recognition》阅读笔记

论文标题 《Deep Residual Learning for Image Recognition》 撑起CV界半边天的论文Residual &#xff1a;主要思想&#xff0c;残差。 作者 何恺明&#xff0c;超级大佬。微软亚研院属实是人才辈出的地方。 初读 摘要 提问题&#xff1a; 更深层次的神经网络更难训练。 …

(vue3)大事记管理系统 文章管理页

[element-plus进阶] 文章列表渲染&#xff08;带搜索&到分页&#xff09; 表单架设&#xff1a;当前el-form标签配置一个inline属性&#xff0c;里面的元素就会在一行显示了 中英国际化处理&#xff1a;App.vue中el-config-provider标签包裹组件&#xff0c;意味着整个组…

【LeetCode高频SQL50题-基础版】打卡第6天:第31~35题

文章目录 【LeetCode高频SQL50题-基础版】打卡第6天&#xff1a;第31~35题⛅前言员工的直属部门&#x1f512;题目&#x1f511;题解 判断三角形&#x1f512;题目&#x1f511;题解 连续出现的数字&#x1f512;题目&#x1f511;题解 指定日期的产品价格&#x1f512;题目&am…

Java实现hack汇编器

Hack汇编语言是一种特定于计算机体系结构的汇编语言&#xff0c;使用Hack架构的机器码指令来编写程序。Hack是一种基于Von Neumann结构的计算机体系结构&#xff0c;由Harvard大学的Nand to Tetris项目开发出来&#xff0c;用于实现计算机硬件和软件。 Hack汇编语言主要用于在…

linux 内核中的pid和前缀树

前言&#xff1a; 写这个文章的初衷是因为今天手写了一个字典树&#xff0c;然后写字典树以后忽然想到了之前看的技术文章&#xff0c;linux kernel 之前的pid 申请方式已经从 bitmap 变成了 基数树&#xff0c;所以打算写文章再回顾一下这种数据结构算法 一、内核中pid的申请…

【学习笔记】minIO分布式文件服务系统

MinIO 一、概述 1.1 minIO是什么&#xff1f; MinIO是专门为海量数据存储、人工智能、大数据分析而设计的对象存储系统。&#xff08;早前流行的还有FastDFS&#xff09; 据官方介绍&#xff0c;单个对象最大可存储5T&#xff0c;非常适合存储海量图片、视频、日志文件、备…

java.sql.SQLFeatureNotSupportedException解决方法

使用MyBatis访问数据库查询数据时报错&#xff1a; Caused by: java.sql.SQLFeatureNotSupportedExceptionat com.alibaba.druid.pool.DruidPooledResultSet.getObject(DruidPooledResultSet.java:1771)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun…

03在命令行环境中创建Maven版的Java工程,了解pom.xml文件的结构,了解Java工程的目录结构并编写代码,执行Maven相关的构建命令

创建Maven版的Java工程 Maven工程的坐标 数学中使用x、y、z三个向量可以在空间中唯一的定位一个点, Maven中也可以使用groupId,artifactId,version三个向量在Maven的仓库中唯一的定位到一个jar包 groupId: 公司或组织域名的倒序, 通常也会加上项目名称代表公司或组织开发的一…

JDBC操作BLOB类型字段

JDBC中Statement接口本身不能直接操作BLOB数据类型 操作BLOB数据类型需要使用PreparedStatement或者CallableStatement(存储过程) 这里演示通过PreparedStatement操作数据库BLOB字段 设置最大传入字节 一般是4M 可以通过以下命令修改 set global max_allowed_packet1024*1…

网页在线打开PDF_网站中在线查看PDF之pdf.js

一、pdf.js简介 PDF.js 是一个使用 HTML5 构建的便携式文档格式查看器。 pdf.js 是社区驱动的&#xff0c;并由 Mozilla 支持。我们的目标是为解析和呈现 PDF 创建一个通用的、基于 Web 标准的平台。 pdf.js 将 PDF 文档转换为 HTML5 Canvas 元素&#xff0c;并使用 JavaScr…

Puppeteer结合测试工具jest使用(四)

Puppeteer结合测试工具jest使用&#xff08;四&#xff09; Puppeteer结合测试工具jest使用&#xff08;四&#xff09;一、简介二、与jest结合使用&#xff0c;集成到常规测试三、支持其他的几种四、总结 一、简介 Puppeteer是一个提供自动化控制Chrome或Chromium浏览器的Node…

MyBatis(中)

目录 1、动态sql&#xff1a; 1、if标签&#xff1a; 2、where标签&#xff1a; 3、 trim标签&#xff1a; 4、set标签&#xff1a; 5、choose when otherwise&#xff1a; 6、模糊查询的写法&#xff1a; 7、foreach标签&#xff1a; &#xff08;1&#xff09;批量删除…

施耐德Unity通过Modbus控制变频器

硬件设备 PLC: Unity Premium (CPU:TSX P57154) 通讯卡: TSX SCP 114 连接电缆: TSX SCP CM 4030 VSD: ATV 58 硬件连接 Unity Premium (CPU: TSX P57154)本身不带Modbus接口&#xff0c;因此&#xff0c;采用TSX SCP 114扩展一个Modbus接口。TSX SCP 114是一个RS-485接…