(数据结构)单链表的相关操作

news/2024/2/28 9:59:43
//1.预编译部分#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>//2.单链表的结构体typedef struct LNode{int data;struct LNode* next;   //因为next指针指向的为结构体类型,所以类型为struct LNode*}LNode, * LinkList;         //代码没执行到最后一步之前,定义结构体还是要把类型名写全,之后才能简化为LNode//3.单链表的初始化void InitLinkList(LinkList L)  //给头结点赋值{L->data = 0;     //头结点的data域用作给链表长度计数L->next = NULL;  //头结点的next域用来指向链表的另一个节点}//4.单链表的打印void PrintLinkList(LinkList L){LNode* p;    //定义一个结构体指针p = L;       //将它指向头指针的位置while (p->next)     //如果其下一个节点不为NULL{p = p->next;    //则把这个指针往后一位,从而输出下一节点的值printf("%d-->", p->data);}printf("NULL\n");  //如果其下一个节点为NULL,则输出NULL}//5.单链表的头插法void HeadInsertLinkList(LinkList L){LNode* NewNode;   //新节点的地址int data;    //新节点中data的值printf("请输入一个数,输入9999结束循环\n");scanf("%d", &data);//malloc()函数的作用为动态分配内存,分配内存的大小有内部参数sizeof()计算可得//给静态地址赋值时要将其强制类型转换为相应指针类型while (data != 9999){//进行插入操作//每次调用malloc函数,就重新在内存中开辟一块指定大小的内存空间给链表节点NewNode = (LNode*)malloc(sizeof(LNode));	//相当于每次创建一个新的链表节点NewNode->next = L->next;	//将头指针中的next赋值给新创建的节点的nextL->next = NewNode;	  //将新建节点的地址赋值给头结点的nextNewNode->data = data;   //将要输入的数赋值给新创建节点的dataL->data++;		//头节点中的data+1,用来计数链表长度//printf("请输入一个数,输入9999结束循环\n");scanf("%d", &data);}}//6.单链表的尾插法创建链表void  TailInsertLinkList(LinkList L){LNode* NewNode; //新节点的地址LNode* TailNode = L;   //为了不改变头节点的位置,故定义一个尾节点来进行相关操作int data;  //新节点中data的值while (TailNode->next != NULL)   //当指向节点的下一个节点不为空时,尾节点一直向后走{TailNode = TailNode->next;}printf("请输入一个数,输入9999结束循环\n");scanf("%d", &data);while (data != 9999){//进行插入操作//每次调用malloc函数,就重新在内存中开辟一块指定大小的内存空间给链表节点NewNode = (LNode*)malloc(sizeof(LNode));  //相当于每次创建一个新的链表节点NewNode->data = data;   //将数值插入新建节点的dataTailNode->next = NewNode;  //将新建的节点连接在尾指节点之后NewNode->next = NULL;   //将新建节点的next赋值为空TailNode = NewNode;  //将尾节点向后一个节点L->data++;		//头节点中的data+1,用来计数链表长度//printf("请输入一个数,输入9999结束循环\n");scanf("%d", &data);      //若输出9999跳出循环结束链表的创建}}//7.按位查找数据元素LNode* GetElem(LinkList L, int i){//(1)判断i的合法性if (i == 0)  //链表为空{printf("你寻找的元素不存在,将返回头结点\n");}if (i<1 || i>L->data)  //当i的位置小于1或大于表长,数据非法{printf("你寻找的元素不存在,将返回NULL\n");}//2.查找数据元素LNode* p = L;   //为了不改变头节点的位置,故定义一个查询节点来进行相关操作for (int j = 1; j <= i; j++)  //移动次数相应位数的次数{p = p->next;    //查询节点后移,第一位是头结点}return p;  //找到目标节点后返回这个节点}//8.按值查找数据元素int* LocatElem(LinkList L, int e, int* count){if (!L->next)  //链表为空则返回头结点{printf("这个链表为空\n");return 0;}LNode* p = L;   //为了不改变头节点的位置,故定义一个查询节点来进行相关操作while (p->next)  //如果查询节点的下一个节点不为空{(*count)++;  //计数器+1p = p->next;  //第一个节点为头结点,需要往后一个节点再判断if (p->data == e){return count;}}printf("你寻找的元素不存在\n");return 0;}//9.单链表的按位插入void LocalInsertLinkList(LinkList L, int i, int e){//(1)判断i的合法性if (i<1 || i>(L->data + 1)){printf("要插入的元素的位置无效\n");}//插入新元素LNode* p = GetElem(L, i - 1);LNode* NewNode = (LNode*)malloc(sizeof(LNode));NewNode->data = e;NewNode->next = p->next;p->next = NewNode;L->data++;}//10.单链表的按位删除void LocalDeletElem(LinkList L, int i, int* e){	//(1)检查i的合法性if (!L->next){printf("这个链表为空\n");*e = 9999;goto x;}if (i<1 || i>(L->data)){printf("要删除的元素不存在\n");*e = 9999;goto x;}//(2)删除指定元素LNode* p = GetElem(L, i - 1);LNode* q = p->next;p->next = q->next;*e = q->data;free(q);L->data--;x:;}//11.销毁单链表void DestoryLinkList(LinkList L){int o;while (L->data){LocalDeletElem(L, 1, &o);PrintLinkList(L);}free(L);}//12.单链表的合并LinkList mergeList(LinkList L1, LinkList L2){LinkList L3 = (LNode*)malloc(sizeof(LNode));LNode* P1 = L1->next;LNode* P2 = L2->next;LNode* P3 = L3;  //防止改变头结点的位置,新建一个节点和头结点指向同一位置,代替指针完成链表的链接while (P1 != NULL && P2 != NULL){if (P1->data <= P2->data){P3->next = P1;P1 = P1->next;}else{P3->next = P2;P2 = P2->next;}P3 = P3->next;}P3->next = P1 == NULL ? P2 : P1;return L3;}//合并两个单链表(相同元素保留一个)LinkList Merge_List(LinkList La, LinkList Lb)/*合并以La,Lb为头结点的两个有序链表*/{LNode* Lc, * pa, * pb, * ptr;LNode* pc = (LNode*)malloc(sizeof(LNode));Lc = La;pc = La;pa = La->next;pb = Lb->next;while (pa != NULL && pb != NULL){if (pa->data < pb->data){pc->next = pa;pc = pa;pa = pa->next;}if (pa->data > pb->data){pc->next = pb;pc = pb;pb = pb->next;}if (pa->data == pb->data){pc->next = pa;pc = pa;pa = pa->next;ptr = pb;pb = pb->next;free(ptr);}}if (pa != NULL)pc->next = pb;elsepc->next = pb;free(Lb);return(Lc);}//单链表的逆置LinkList converse(LinkList head){LinkList p,  q;p = head->next;head->next = NULL;while (p){/*向后挪动一个位置*/q = p;p = p->next;/*头插*/q->next = head->next;head->next = q;}}int main(){LinkList L1;   //L是一个结构体指针——为头指针L1 = (LNode*)malloc(sizeof(LNode));  //申请内存只能在主函数中完成,放在(除结构体指针类型)的自定义函数中时会随着函数的调用结束内存释放而失效//给头结点赋值//InitLinkList(L1);//头插法创建链表//HeadInsertLinkList(L1);打印链表//PrintLinkList(L1);//_______________________________________________________________________//给头结点赋值InitLinkList(L1);//尾插法创建链表TailInsertLinkList(L1);//打印链表PrintLinkList(L1);LinkList L2;L2 = (LNode*)malloc(sizeof(LNode));//给头结点赋值InitLinkList(L2);//尾插法创建链表TailInsertLinkList(L2);//打印链表PrintLinkList(L2);//_______________________________________________________________________//按位查找数据元素int i;printf("请输入需要查找的位数\n");scanf("%d", &i);printf("链表L1第%d位的data=%d\n", i, GetElem(L1, i)->data);//_______________________________________________________________________//按值查找数据元素int e;int count = 0;printf("请输入需要查找的数据\n");scanf("%d", &e);printf("%d在链表L1的第%d位\n", e, *(LocatElem(L1, e, &count)));//_______________________________________________________________________//单链表的按位插入int n = 0;int m = 0;printf("请输入要插入的位置\n");scanf("%d", &n);printf("请输入要插入的值\n");scanf("%d", &m);LocalInsertLinkList(L1, n, m);PrintLinkList(L1);//_______________________________________________________________________//单链表的按位删除int d;int q;printf("请输入需要删除的位数\n");scanf("%d", &q);LocalDeletElem(L1, q, &d);PrintLinkList(L1);//_______________________________________________________________________//销毁单链表/*DestoryLinkList(L1);*///—————————————————————————————————————//合并单链表printf("合并后的单链表:\n");LinkList h;h = Merge_List(L1, L2);PrintLinkList(h);//单链表的逆置//打印链表printf("逆置后的链表\n");PrintLinkList(converse(h));return 0;}


http://www.ppmy.cn/news/1164473.html

相关文章

第七章:最新版零基础学习 PYTHON 教程—Python 列表(第八节 -在 Python 中获取列表作为用户的输入)

我们经常遇到需要将数字/字符串作为用户输入的情况。在本文中,我们将了解如何使用Python从用户处获取输入列表。 目录 使用Loop在 Python 中获取用户输入的列表 Python3

Qt move和setGeometry的区别

move 和 setGeometry 都是用于管理窗口或小部件的位置的方法&#xff0c;通常在使用 Qt 编程时会用到。它们之间的主要区别在于&#xff1a; move 方法&#xff1a;这个方法用于设置小部件的左上角的坐标位置&#xff0c;它需要两个参数&#xff0c;即横坐标和纵坐标。使用 mov…

CentOS | 添加普通用户并授权sudo

sudo -i adduser peter passwd peter whereis sudoers nano /etc/sudoers添加一行新用户到root组 ## Allow root to run any commands anywhere root ALL(ALL) ALL peter ALL(ALL) ALL如果提升权限后无法cd到其他目录等&#xff0c;修改 /etc/passwd 文件&…

简单秒表设计仿真verilog跑表,源码/视频

名称&#xff1a;简单秒表设计仿真 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 秒表显示最低计时为10ms&#xff0c;最大为59:99&#xff0c;超出返回00&#xff1a;00 具有复位、启动、暂停三个按键 四个数码管分别显示4个时间数字。 演示…

replace、replaceAll、replaceFirst的区别

replace、replaceAll和replaceFirst是Java中常用的替换字符的方法,它们的方法定义是&#xff1a; replace(CharSequence target, CharSequence replacement) &#xff0c;用replacement替换所有的target&#xff0c;两个参数都是字符串。 replaceAll(String regex, String repl…

Qt ModelViewDelegate(模型-视图-代理) 介绍和使用

一、Model (模型) 介绍 Qt Model 是 Qt 的一个重要组件&#xff0c;用于管理和展示数据。它是 Qt 的 Model/View 架构的核心部分&#xff0c;用于将数据模型与其视图相分离&#xff0c;实现数据的高效处理和可视化呈现。 Qt Model 可以理解成一组数据结构&#xff0c;其中包含…

开源OA协同办公系统,集成Flowable流程引擎 可拖拽创建个性表单

源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88403340 源码下载2&#xff1a; 关注我留言 开源OA协同办公系统&#xff0c;集成Flowable流程引擎 可拖拽创建个性表单。基于RuoYi-VUE版本开发。 1、使用RuoYi-Vue的基础上开发。 2、集成flowable&a…

【软件安装】docker 安装 elasticsearch 和 kibana

首先根据需要选择相应的版本号&#xff0c;然后分别执行下面的脚本 install_elasticsearch.sh docker run -it --name es_710 \-p 9200:9200 \-p 9300:9300 \-e "discovery.typesingle-node" \-e ES_JAVA_OPTS"-Xms5g -Xmx10g" \-e "TAKE_FILE_OWNE…

day5:Node.js 第三方库

day5:Node.js 第三方库 文章目录 day5:Node.js 第三方库使用 Express.js 构建 Web 应用安装 Express第一个 Express 框架实例第二个 Express 框架实例Node.js 连接 MySQL查询数据插入数据更新数据删除数据使用 Express.js 构建 Web 应用 Express框架是Node.js生态系统中的一…

智能井盖是什么?万宾科技智能井盖传感器有什么特点

智能井盖是一种基于物联网和人工智能技术的新型城市设施。它不仅具备传统井盖的功能&#xff0c;还能通过数字化、自动化的方式实现远程监控和智能管理&#xff0c;提升城市运行效率和服务水平。 WITBEE万宾智能井盖传感器EN100-C2是一款井盖异动监测的传感终端。对窨井盖状态(…

Kubernetes基础概念及架构和组件

目录 一、kubernetes简介 1、kubernetes的介绍与作用 2、为什么要用K8S&#xff1f; 二、kubernetes特性 1、自我修复 2、弹性伸缩 3、服务发现和负载均衡 4、自动发布&#xff08;滚动发布/更新&#xff09;和回滚 5、集中化配置管理和密钥管理 6、存储编排 7、任务批…

tlaplus-vscode插件使用记录

参考官方教程Getting Started 和油管视频A gentle intro to TLA 入门和命令 首先在vscode的扩展里面下载 然后新建一个squares.tla文件 在代码区域先输入module生成上下的分隔符&#xff0c;然后输入pluscal来调用模版&#xff0c;生成一堆预设代码 小改一下&#xff0c;编写一…

云原生之Docker

docker 初识Docker什么是DockerDocker与虚拟机Docker相关术语及架构镜像和容器DockerHubDocker架构 Docker命令镜像操作命令容器操作命令数据卷命令 自定义镜像镜像结构Dockerfile DockerCompose安装常用命令 初识Docker 什么是Docker docker是一个快速交付应用&#xff0c;运…

postgresql(openGauss)模糊匹配参数

被pg系这个show要求精准匹配参数恶心的不轻。 原理是用.psqlrc&#xff08;openGauss用.gsqlrc&#xff09;文件set一个select常量进去&#xff0c;需要用&#xff1a;调用这个常量。理论上也可以增强其他的各种功能。 我在openGauss做的一个例子 .gsqlrc&#xff08;.psqlrc…

似然函数和贝叶斯的关系

似然函数 什么是似然函数似然函数到底是 L ( θ ∣ x ) L(\theta|x) L(θ∣x)还是 L ( x ∣ θ ) L(x|\theta) L(x∣θ)似然函数和贝叶斯估计的关系是什么&#xff1f;先验分布是均匀的&#xff1a; P ( θ ) 1 P(\theta) 1 P(θ)1。概率密度和概率有什么区别&#xff1f; 什…

计算未来:微软眼中的人工智能

计算未来 :人工智能及其社会角色&#xff08;The Future Computed. Artificial Intelligence and its role in society &#xff09;这本书于2018年09月由北京大学出版社出版。 书籍的作者是&#xff1a;沈向洋&#xff08;微软全球执行副总裁&#xff09;,&#xff08;美&…

call函数和apply函数的区别

call和apply是 JavaScript 中的两个函数方法&#xff0c;用于调用函数并指定函数内部的this值以及传递参数。它们的主要区别在于参数的传递方式。 call方法&#xff1a;call方法允许你在调用函数时&#xff0c;显式地指定函数内部的this值和参数列表。它的语法为&#xff1a; …

目标检测YOLO实战应用案例100讲-基于改进YOLO v7的智能振动分拣系统开发

目录 前言 课题国内外研究现状 物料分拣研究现状 目标检测算法研究现状

需要在js中避免的几个常见错误

需要在js中避免的10个常见错误 误解变量作用域 在我们的代码的特定区域中&#xff0c;变量的可访问性被称为变量范围&#xff0c;这是编程中的一个基本概念。对变量范围的误解是JavaScript中最常见的编程错误之一&#xff0c;它会导致意想不到的行为&#xff0c;使得调试非常…

【Leetcode】215. 数组中的第K个最大元素

一、题目 1、题目描述 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例1: 输入: [3,2,1,5,6,4], k = 2 输出…
最新文章