30.链表练习题(1)(王道2023数据结构2.3.7节1-15题)

【前面使用的所有链表的定义在第29节】

试题1:

设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。

首先来看非递归算法,暴力遍历:

int Del(LinkList &L,ElemType x){
//此函数实现删除链表中为x的元素LNode *p,*q;p = L;  //p指向头结点q = L->next;  //q指向首元结点while(q->next!=NULL){if(q->data == x){p->next = q->next;free(q);q = p->next;}else{p = p->next;q = q->next;}}return 0;
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);Del(L, 3);PrintList(L);return 0;
}

然后看递归算法:

int Del(LinkList &L,ElemType x){
//此函数实现递归删除链表中为x的元素LNode *p;if(L==NULL)return 0;if(L->data==x){p = L;L = L->next;free(p);Del(L, x);}else{Del(L->next, x);}return 0;
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);Del(L, 3);PrintList(L);return 0;
}

这里分析一下怎么递归的:从头开始,如果首元结点就是被删掉的x那很显然;如果不是,这时候执行Del(L->next, x),如果第2个是被删掉的元素,进入if(L->next->data==x)分支,此时p=L实际上执行p=L->next,p指向了第2个被删除的结点;第2行L = L->next执行的是L->next=L->next->next,把首元结点的next域修改为指向第3个结点;然后free(p)释放空间,最后继续执行Del(L,x)相当于Del(L->next, x),这时L->next是第3个结点,依次递归。

试题2:(与题1差不多)

试题3:L是带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值

此题可以使用栈来解决,这里主要提书上的递归方法:

void AdversePrint(LinkList L){
//此函数实现反向打印链表L的元素if(L!=NULL){AdversePrint(L->next);  //递归printf("[%d] ", L->data);  //打印当前元素}
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);AdversePrint(L->next); //带头结点的链表,这里L->next指向首元结点return 0;
}

试题4:编写在带头结点的单链表L中删除一个最小值结点的高效算法。

(注意不要写野指针!)

void Deletexmin(LinkList &L){
//此函数实现删除链表最小值元素LNode *p, *q, *m, *n;int a;p = L;  //p指向头结点q = L->next;  //q指向首元结点a = q->data;  //首元结点元素赋给am = p;n = q;while (q->next != NULL){q = q->next;  //指针后移p = p->next;  //指针后移if(q->data < a){a = q->data;  //更新am = p;  //记录当前最小值的前驱结点n = q;  //记录当前最小值结点}}m->next = n->next;free(n);
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);Deletexmin(L);PrintList(L);return 0;
}

试题5:将单链表的元素就地逆置

利用头插法重新建立链表:

void ReverseL(LinkList &L){
//此函数实现逆置单链表所有元素LNode *p, *q;p = L;q = L->next;  //q指向首元结点p = q;q = q->next;  //q指向第二个结点p->next = NULL;if(q==NULL)return ;else{while (q!=NULL){p = q->next;  //p移向首元结点q->next = L->next; L->next = q;  //修改头结点指针,头插法q = p;}	}
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);ReverseL(L);PrintList(L);return 0;
}

试题6:有一个带头结点的单链表L,设计算法使其递增有序。

采用插入排序的思想:

void SortL(LinkList &L){
//此函数实现递增排序单链表所有元素LNode *p, *q, *r;p = L->next;  //p工作在排好序的链表q = p->next;  //q是待排序元素,即第二个结点,断开之后的第一个结点r = q->next;  //r在q之后p->next = NULL;  //断开while(q!=NULL){r = q->next;p = L;  while(q->data > p->next->data && p->next!=NULL){p = p->next;}q->next = p->next;p->next = q;q = r;}
}int main(){LinkList L;InitList(L);Create(L);PrintList(L);SortL(L);PrintList(L);return 0;
}

输出:

请输入要输入元素的个数:5
请输入第1元素的值:5
请输入第2元素的值:3
请输入第3元素的值:1
请输入第4元素的值:2
请输入第5元素的值:4
当前单链表的所有元素:[5] [3] [1] [2] [4]
当前单链表的所有元素:[1] [2] [3] [4] [5]

试题7:(修改试题1的参数条件if(q->data == x)即可)

试题8:求两个链表的公共链表

如果有公共链表,一定是这样的Y型拓扑结构:

int LengthL(LinkList L){
//此函数实现求解链表长度LNode *p;p = L;int i = 0;while(p->next!=NULL){p = p->next;i++;}return i;
}LinkList Search_1st_common(LinkList L1,LinkList L2){
//此函数实现查找两个链表的公共结点int L1length = LengthL(L1);int L2length = LengthL(L2);printf("%d", LengthL(L1));printf("%d", LengthL(L2));int delta = 0;  //记录长链表比短链表多多少LNode *longList, *shortList;if(L1length > L2length){longList = L1->next;  //L1更长,longList指向L1首元结点shortList = L2->next;delta = L1length - L2length;}else{longList = L2->next;  //L2更长,longList指向L2首元结点shortList = L1->next;delta = L2length - L1length;}printf("%d", longList->data);printf("%d", shortList->data);printf("%d", delta);for (int i = 0; i < delta;i++){ // 移动longList指针至delta位置longList = longList->next;}printf("%d", longList->data);//经过以上移动,此时longList指针与shortList指针指的剩余长度一样while (longList!=shortList && longList != NULL){longList = longList->next;shortList = shortList->next;}return longList;
}void PrintResult(LinkList L){if(L == NULL)printf("公共结点不存在!");elsePrintList(L);
}int main(){LinkList L1,L2;InitList(L1);Create(L1);PrintList(L1);InitList(L2);Create(L2);PrintList(L2);PrintResult(Search_1st_common(L1, L2));return 0;
}

输出:

请输入要输入元素的个数:2
请输入第1元素的值:1
请输入第2元素的值:2
当前单链表的所有元素:[1] [2]
请输入要输入元素的个数:5
请输入第1元素的值:3
请输入第2元素的值:4
请输入第3元素的值:5
请输入第4元素的值:6
请输入第5元素的值:7
当前单链表的所有元素:[3] [4] [5] [6] [7]
253136公共结点不存在!请输入要输入元素的个数:2
请输入第1元素的值:1
请输入第2元素的值:2
当前单链表的所有元素:[1] [2]
请输入要输入元素的个数:3
请输入第1元素的值:3
请输入第2元素的值:4
请输入第3元素的值:5
当前单链表的所有元素:[3] [4] [5]
233114公共结点不存在!

在写这段代码的时候踩了一个坑:大家观察下面两段代码:

void Search_1st_common(){
//此函数实现查找两个链表的公共结点int L1length = 3;int L2length = 5;int delta = 0;  //记录长链表比短链表多多少if(L1length > L2length){delta = L1length - L2length;}else{delta = L2length - L1length;}printf("%d", delta);
}int main(){Search_1st_common();return 0;
}
void Search_1st_common(){
//此函数实现查找两个链表的公共结点int L1length = 3;int L2length = 5;int delta = 0;  //记录长链表比短链表多多少if(L1length > L2length){int delta = L1length - L2length;}else{int delta = L2length - L1length;}printf("%d", delta);
}int main(){Search_1st_common();return 0;
}

打印delta的结果分别是2和0.后一段代码中if...else...结构体内相当于重新定义了一个delta,当结构体执行结束后又被释放掉了,所以delta的返回结果是0.

试题9:试写出算法:按递增次序输出单链表中各节点的数据元素,并释放结点所占的内存空间。

此题可以仿照试题4.不多解释。

void Printelement(LinkList &L){
//此函数实现按递增次序输出单链表数据元素,并释放结点所占的存储空间LNode *p, *q; // q记录了每次遍历的最小值结点的前驱int min;while(L->next!=NULL){  //最后结束条件是L删成空p = L;q = L;min = p->next->data;  //第1个元素while(p->next != NULL){if(p->next->data < min){min = p->next->data;q = p;}p = p->next;}printf("[%d]", q->next->data);p = q->next;q->next = p->next;free(p);}
}int main(){LinkList L1;InitList(L1);Create(L1);PrintList(L1);Printelement(L1);return 0;
}

试题10:将一个链表A分解成两个链表A和B,使得A表中含有原表中序号是奇数的元素,B表中含有原表中序号是偶数的元素。

这里不采用书上写的设置访问序号变量。由于有周期性,适当控制指针即可:

void Printelement(LinkList &L){
//此函数实现将一个链表A分解成两个链表A和B,使得A表中含有原表中序号是奇数的元素,B表中含有原表中序号是偶数的元素。LNode *p, *q, *r;  //r指针工作在新链表中LinkList L0;  //L0相当于题目中的BInitList(L0);p = L->next;q = p->next;  //q指向第2个结点r = L0;while(p!=NULL&&q!=NULL){r->next = q;p->next = q->next;if(p->next == NULL)break;p = p->next;if(q->next == NULL)break;q = p->next;r = r->next;r->next = NULL;}PrintList(L);PrintList(L0);
}int main(){LinkList L1;InitList(L1);Create(L1);PrintList(L1);Printelement(L1);return 0;
}

输出:

当前单链表的所有元素:[1] [2] [3] [4] [5] [6]
当前单链表的所有元素:[1] [3] [5]
当前单链表的所有元素:[2] [4] [6]当前单链表的所有元素:[1] [2] [3] [4] [5] [6] [7]
当前单链表的所有元素:[1] [3] [5] [7]
当前单链表的所有元素:[2] [4] [6]

试题11:设C=\left \{ a_1,b_1,a_2,b_2...a_n,b_n \right \}为线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分成两个线性表,使得A=\left \{ a_1,a_2...a_n \right \}B=\left \{ b_n,b_{n-1}...b_1 \right \}

此题跟第10题很像,修改指针即可。

void Printelement(LinkList &L){
//此函数实现将一个链表A分解成两个链表A和B,使得A表中含有原表中序号是奇数的元素,B表中含有原表中序号是偶数倒序的元素。LNode *p, *q, *r;  //r指针工作在新链表中LinkList L0;  //L0相当于题目中的BInitList(L0);p = L->next;q = p->next;  //q指向第2个结点r = L0->next;while(p!=NULL&&q!=NULL){L0->next = q;  //头插法p->next = q->next;q->next = r;if(p->next == NULL)break;p = p->next;if(p->next == NULL)break;q = p->next;r = L0->next;}PrintList(L);PrintList(L0);
}int main(){LinkList L1;InitList(L1);Create(L1);PrintList(L1);Printelement(L1);return 0;
}

输出:

当前单链表的所有元素:[1] [2] [3] [4] [5] [6]
当前单链表的所有元素:[1] [3] [5]
当前单链表的所有元素:[6] [4] [2]

试题12:在一个递增有序的单链表中,删除所有数值相同的元素,使表中不再有重复的元素。

void DeleteSame(LinkList &L){
//此函数实现把递增单链表的重复元素删除LNode *p, *q;p = L->next; //第一个元素q = p->next;while(q!=NULL){if(p->data == q->data){q = q->next;free(p->next);p->next = q;}else{p = p->next;q = q->next;}}
}int main(){LinkList L1;InitList(L1);Create(L1);PrintList(L1);DeleteSame(L1);PrintList(L1);return 0;
}

输出:

当前单链表的所有元素:[1] [2] [2] [3] [3] [4] [4] [5]
当前单链表的所有元素:[1] [2] [3] [4] [5]

试题13:假设有两个按元素值递增次序排列的线性表,以单链表形式存储。编写算法把这两个单链表归并为一个按元素值递减的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。

此题属于简单题,最后使用头插法倒序即可。

LinkList Merge(LinkList L1,LinkList L2){
//此函数实现把两个递增的单链表合并成递减的单链表LNode *p, *q;  //L1指针LNode *m, *n;  //L2指针LNode *r;  //新表,头插法LinkList L;InitList(L);  //初始化p = L1->next;  //L1第1个结点m = L2->next;  //L2第1个结点q = p->next;  //L1第2个结点n = m->next;  //L2第2个结点r = L->next;  while(L1->next!=NULL && L2->next!=NULL){if(p->data < m->data){L->next = p;p->next = r;p = q;r = L->next;if(q == NULL)break;q = q->next;}else{L->next = m;m->next = r;m = n;r = L->next;if(n == NULL)break;n = n->next;}}if(L1->next == NULL){while(L2->next!=NULL){L->next = m;m->next = r;m = n;r = L->next;if(n == NULL)break;n = n->next;}}else{while(L1->next!=NULL){L->next = p;p->next = r;p = q;r = L->next;if(q == NULL)break;q = q->next;}}return L;
}int main(){LinkList L1, L2;InitList(L1);Create(L1);PrintList(L1);InitList(L2);Create(L2);PrintList(L2);PrintList(Merge(L1,L2));return 0;
}

输出:

请输入要输入元素的个数:3
请输入第1元素的值:1
请输入第2元素的值:2
请输入第3元素的值:4
当前单链表的所有元素:[1] [2] [4]
请输入要输入元素的个数:2
请输入第1元素的值:1
请输入第2元素的值:2
当前单链表的所有元素:[1] [2]
当前单链表的所有元素:[4] [2] [2] [1] [1]

试题14:设A和B是两个单链表(带头结点),其中元素递增有序,设计一个算法从A和B中公共元素产生单链表C,要求不破坏A,B的结点。

LinkList Intersection(LinkList L1,LinkList L2){
//此函数实现产生单链表,包含两个链表的公共元素LNode *p;  //L1指针LNode *q;  //L2指针LNode *r;  //新表的指针LinkList L;InitList(L);p = L1->next;q = L2->next;r = L;while(p!=NULL && q!=NULL){if(p->data < q->data){p = p->next;}else if(p->data = q->data){LNode *s = (LNode *)malloc(sizeof(LNode));s->data = p->data;s->next = NULL;r->next = s;r = r->next;p = p->next;  //后移q = q->next;}else{q = q->next;}}return L;
}int main(){LinkList L1, L2;InitList(L1);Create(L1);PrintList(L1);InitList(L2);Create(L2);PrintList(L2);PrintList(Intersection(L1,L2));return 0;
}

输出:

请输入要输入元素的个数:4
请输入第1元素的值:1
请输入第2元素的值:2
请输入第3元素的值:3
请输入第4元素的值:4
当前单链表的所有元素:[1] [2] [3] [4]
请输入要输入元素的个数:4
请输入第1元素的值:2
请输入第2元素的值:3
请输入第3元素的值:4
请输入第4元素的值:5
当前单链表的所有元素:[2] [3] [4] [5]
当前单链表的所有元素:[2] [3] [4]

试题15:此题要求同14,但要求合并链表存储在A中。

LinkList Intersection(LinkList L1,LinkList L2){
//此函数实现产生单链表,包含两个链表的公共元素LNode *p, *m; // L1指针,m保存待删结点的前驱,p待删结点LNode *q;  //L2指针m = L1;p = L1->next;q = L2->next;while(p!=NULL && q!=NULL){if(p->data < q->data){m->next = p->next;free(p);p = m->next;}else if(p->data == q->data){p = p->next;q = q->next;m = m->next;}else{q = q->next;}}if(q == NULL){while(p!=NULL){m->next = p->next;free(p);p = m->next;}}return L1;
}int main(){LinkList L1, L2;InitList(L1);Create(L1);PrintList(L1);InitList(L2);Create(L2);PrintList(L2);PrintList(Intersection(L1,L2));return 0;
}

输出:

当前单链表的所有元素:[3] [5] [7] [9]
当前单链表的所有元素:[4] [5] [8] [9]
当前单链表的所有元素:[5] [9]当前单链表的所有元素:[2] [3] [4] [5]
当前单链表的所有元素:[1] [2] [3] [4]
当前单链表的所有元素:[2] [3] [4]当前单链表的所有元素:[5] [6] [7] [8]
当前单链表的所有元素:[1] [2] [3] [4]
当前单链表的所有元素:

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

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

相关文章

科技云报道:分布式存储红海中,看天翼云HBlock如何突围?

科技云报道原创。 过去十年&#xff0c;随着技术的颠覆性创新和新应用场景的大量涌现&#xff0c;企业IT架构出现了稳态和敏态的混合化趋势。 在持续产生海量数据的同时&#xff0c;这些新应用、新场景在基础设施层也普遍基于敏态的分布式架构构建&#xff0c;从而对存储技术…

SpringBoot项目(百度AI整合)——如何在Springboot中使用语音文件识别 ffmpeg的安装和使用

前言 前言&#xff1a;在实际使用中&#xff0c;经常要参考官方的案例&#xff0c;但有时候因为工具的不一样&#xff0c;比如idea 和 eclipse&#xff0c;普通项目和spring项目等的差别&#xff1b;还有时候因为水平有限&#xff0c;难以在散布于官方的各个文档读懂&#xff…

【owt】vs2022 + v141 : 查看WINDOWSSDKDIR

confmfc改为vs2022 + v141 构建 去掉这几个boost库,一样可以链接ok libboost_system-vc141-mt-sgd-x32-1_67.lib libboost_date_time-vc141-mt-sgd-x32-1_67.lib libboost_random-vc141-mt-sgd-x32-1_67.libSDK不在2022或者2017 里面? WINDOWSSDKDIR 在哪里? ##

1786_MTALAB代码生成把通用函数生成独立文件

全部学习汇总&#xff1a; GitHub - GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes…

PCIE基础知识-3

PCIE 三种传输方式&#xff1a;IO中断&#xff0c;DMA&#xff0c;peer to peer 中断&#xff1a;PCI设备需要向内存&#xff08;SDRAM&#xff09;中写入一些数据&#xff0c;该PCI设备会向CPU请求一个中断&#xff0c;然后CPU首先先通过PCI总线把该PCI设备的数据读取到CPU内…

解读未知--文档图像大模型的探索与应用

前言&#xff1a; 近日&#xff0c;合合信息在多模态大模型与文档图像智能理解专题论坛上进行了分享。多模态大模型指的是能够处理多种语义信息的一种深度学习模型。文档图像智能理解则是指对文档和图像进行智能化解析和理解的技术。合合信息在这个领域的分享&#xff0c;无疑将…

编译原理.龙书学习1

第一章&#xff1a; 编译器&#xff1a;将程序翻译成一种能够被计算机执行的形式 解释器&#xff1a;解释器直接利用用户提供的输入执行源程序中指定的操作 一个编译器的结构 编译器将源程序映射为语义上等价的目标程序&#xff0c;这个映射过程由两部分组成&#xff1a;分析…

黑马JVM总结(二十二)

&#xff08;1&#xff09;类的结构-field 成员变量信息 类字节码里的一些简单表示&#xff1a; &#xff08;2&#xff09;类文件结构-method-init &#xff08;3&#xff09;类文件结构-method-main &#xff08;4&#xff09;类文件结构-附加属性

Mojo:新型AI语言中的7个令人惊叹的Python升级,用简单的英语解释人工智能

Mojo&#xff1a;新型AI语言中的7个令人惊叹的Python升级 编程之美 用简单的英语解释人工智能 编程之美 由Coding Beauty设计的图像&#xff0c;使用Mojo标志和Python标志。 它比C更快&#xff0c;与Python一样简单&#xff0c;但速度提高了35000倍。 进入Mojo&#xff1a;一种…

Northstar 量化平台

基于 B/S 架构、可替代付费商业软件的一站式量化交易平台。具备历史回放、策略研发、模拟交易、实盘交易等功能。兼顾全自动与半自动的使用场景。 已对接国内期货股票、外盘美股港股。 面向程序员的量化交易软件&#xff0c;用于期货、股票、外汇、炒币等多种交易场景&#xff…

【MySQL集群二】使用MyCat和ProxySql代理MySQL集群

中间件代理MySQL MyCat安装MyCat介绍&#xff1a;步骤1&#xff1a;安装Java环境步骤2&#xff1a;下载并解压Mycat步骤3&#xff1a;配置Mycat步骤4&#xff1a;启动Mycat ProxySql安装ProxySql介绍&#xff1a;步骤1&#xff1a;更新系统步骤2&#xff1a;安装ProxySQL步骤3&…

微信小程序快速入门01(含案例)

文章目录 前言一、组件1.常用视图容器类组件viewscroll-viewswiper、swiper-item 2.text、rich-text3.其他常用组件buttonimagenavigator 二、小程序API三、数据绑定1.定义页面数据2.绑定数据 四、事件绑定1.什么是事件2.小程序中常用的事件3.事件对象 的属性列表target和curre…

详解Renko图表如何表现价格变动

相信大多数投资者与FPmarkets澳福一样&#xff0c;都已发现Renko图表与日本烛台图一样&#xff0c;具有上升和下降的特性。增长期间的典型砖块颜色为绿色或白色&#xff0c;而衰退期前的Renko则呈现红色或黑色。 今天&#xff0c;FPmarkets澳福将与各位投资者共同探讨Renko图表…

第一个 Go 程序“hello,world“ 与 main 函数

第一个 Go 程序"hello&#xff0c;world" 与 main 函数 文章目录 第一个 Go 程序"hello&#xff0c;world" 与 main 函数一.创建“hello&#xff0c;world”示例程序二. “hello&#xff0c;world” 程序结构拆解三、main 函数四、Go 语言中程序是怎么编译…

PowerDesigner 连接 MYSQL

我使用的是powerDesigner16的版本&#xff0c;使用前先保证安装了 mysql odbc 驱动包 选择&#xff1a;文件 -> 反向工程 -> database… 一大波图片正在来袭。。。 点击确认 至此连接成功

【JavaScript保姆级教程】Javascript常量

文章目录 前言一、常量1.1 常量是什么1.2 常量的作用 二、示例代码2.1 示例1&#xff1a;声明一个常量2.2 示例2&#xff1a;常量的命名规则2.3 示例3&#xff1a;常量与变量的区别 总结 前言 欢迎来到【JavaScript保姆级教程】&#xff01;在本篇教程中&#xff0c;我们将讨论…

【激光雷达码盘偏摆角的真假点映射关系】

激光雷达码盘偏摆角的真假点映射关系 一、概要二、完架构流程三、技术细节四、完整代码 一、概要 本代码主要计算激光雷达码盘偏摆角&#xff08;也可以理解为雷达的零位角&#xff09;导致的实际slam建图距离的偏差&#xff0c;只取了第一个象限作为分析目标。最终得出的结论是…

浅谈Deep Learning 与 Machine Learning 与Artificial Intelligence

文章目录 三者的联系与区别 三者的联系与区别 “Deep Learning is a kind of Machine Learning, and Machine Learning is a kind of Artificial Intelligence.” 人工智能&#xff08;AI&#xff09;&#xff0c;机器学习&#xff08;Machine Learning&#xff0c;简称ML&am…

41. Linux系统配置FTP服务器并在QT中使用QFtp实现文件上传

1. 说明 这篇博客主要记录一些在Linux系统中搭建FTP服务器时踩过的一些坑,以及在使用QFtp上传文件时需要注意的问题。 2. FTP环境搭建 在linux系统中,需要安装vsftpd,可以在终端中输入下面的命令进行安装: sudo apt-get install vsftpd使用上述命令安装后,系统中会有一…

价值1000的情感爆文写作prompt,助你写出10万+阅读微信爆文

原文&#xff1a;价值1000的情感爆文写作prompt&#xff0c;助你写出10万阅读微信爆文 - 知乎 是否经常看到一些自媒体晒出这样的图片&#xff1f; 或者是这样的10w的阅读文章 那么这是真实能赚钱的吗&#xff1f;还是自媒体夸大其说&#xff0c;吸引流量。 我们先简单了解什…