修正《啊哈算法》上模拟链表算法的错误
算法描述:
在《啊哈算法》上有介绍模拟链表的实现。链表这种数据结构可以通过数组来实现,我们需要两个数组,其中一个数组data存放数据,即数据域。另外一个数组right用来存放每一个数的右边的数的位置,即指针域。
在上图中,列如data[3]的下一个元素是data[4],下标为4 ,所以right[3]的值为4。又因为data[9]后没有元素,所以right[9]的值用0表示。
如果我们要在data[4]数字8之前插入数字6,只需将6放到data数组末尾data[10],接下来将right[3]指向10,将right[10]指向4。
算法实现(上):
代码参考了《啊哈算法》上的实现,但实际上书上的代码是有问题的。
/*核心思路:
查找是否存在一个节点的下一个节点的数据大于待插入的节点,即data[right[t]]>data[len]
如果找到了,就修改right指针域。最后根据right指针域打印其数据域的值
*/
#include <stdio.h>
int data[101];
int right[101];//每个节点都有一个指针域,所以这里的数组长度要和data数组一样长
int main(){/*n为用户首次录入的节点总数,用于控制初始化节点时的循环次数len为当前节点总数,为方便操作,data[0]和right[0]不放内容,从下标1开始遍历,因此data[len]就是最后一个元素*/int n,i,len,t;scanf("%d",&n);//初始化数组datafor(i = 1;i<=n;i++){scanf("%d",&data[i]);}len = n;//初始化数组rightfor(i = 1;i<=n;i++){if(i!=n){right[i] = i+1;}else{right[i] = 0;//用0表示没有下一个元素}}//在data的末尾添加一个数len++;scanf("%d",&data[len]);/*通过遍历指针域,当找到某个节点的数据值大于插入的节点data[len]时,调整指针域的指向。直到指针域遍历完成为止*/t = 1;while(t!=0){if(data[right[t]]>data[len]){right[len] = right[t];right[t] = len;break; }t = right[t];}t = 1;while(t!=0){printf("%d ",data[t]);t = right[t];}//等待用户键盘录入,以起到暂停程序目的getchar();getchar();return 0;
}
程序验证:
第一组:
3
1 3 5
4
输出:1 3 4 5
第二组:
3
1 3 5
7
输出:1 3 5
第三组:
1
3
1
输出:3
测试发现,当用户要插入的数据小于data[1]或者大于最后一个数时,结果输出有误。
结合下面的代码段和这张图可知,当待插入数小于第一个数时,程序是将data[2]和插入数据进行比较;若是待插入的数大于最后一个数,当程序执行到right[t]==0时,由于data[0]未定义,程序也将不会进入if语句段修改其指针域。
t = 1;while(t!=0){if(data[right[t]]>data[len])
算法修正
既然当待插入数大于最后一个数时,没有进入if(data[right[t]]>data[len])语句块,那么只需做一个标记,当未进入该语句块后,就修改最后一个数和倒数第二个数的指针域。
当插入数小于第一个数时,比如对于下面这种情况,由于right数组表示的是指向下一个节点的值,所以直接更改right[1]的值并不正确。
后来想到了可以添加一个头节点,即添加一个right[0],这样当插入数小于第一个数时,只需修改right[0]和right[len]两个指针域即可。
算法实现(下):
/*
核心思路:查找是否存在一个节点的下一个节点的数据大于待插入的节点,即data[right[t]]>data[len]
如果找到了,就修改right指针域。最后根据right指针域打印其数据域的值
*/
#include <stdio.h>
int data[101];
int right[101];//每个节点都有一个指针域,所以这里的数组长度要和data数组一样长
int main(){/*n为用户首次录入的节点总数,用于控制初始化节点时的循环次数len为当前节点总数,为方便操作,data[0]和right[0]不放内容,从下标1开始遍历,因此data[len]就是最后一个元素*/int n,i,len,t;int flag = 1;scanf("%d",&n);//初始化数组datafor(i = 1;i<=n;i++){scanf("%d",&data[i]);}len = n;//初始化数组rightfor(i = 0;i<=n;i++){if(i!=n){right[i] = i+1;}else{right[i] = 0;//用0表示没有下一个元素}}//在data的末尾添加一个数len++;scanf("%d",&data[len]);/*通过遍历指针域,当找到某个节点的数据值大于插入的节点data[len]时,调整指针域的指向。直到指针域遍历完成为止*/t = 1;//对插入节点小于第一个节点的情况做特殊处理。(这里放在if..else里是出于无需再走循环的目的)if(data[len]<data[1]){right[0] = len;right[len] = 1;}else{while(t!=0){if(data[right[t]]>data[len]){flag = 0;right[len] = right[t];right[t] = len;break; }t = right[t];}//插入节点大于最后一个节点的情况 if(flag == 1){right[len] = 0;/*这里只做简单处理,也可以查找right[t]==0的节点修改其指针域,只需在上面循环中加入if(right[t]==0){temp = t;}这里再改成right[temp] = len;*/right[len-1] = len;}}//t为right[0]头节点指向的首节点的下标 t = right[0];while(t!=0){printf("%d ",data[t]);t = right[t];}//等待用户键盘录入,以起到暂停程序目的getchar();getchar();return 0;
}
程序验证:
第一组:
3
1 3 5
4
输出:1 3 4 5
第二组:
3
1 3 5
7
输出:1 3 5 7
第三组:
1
3
1
输出:1 3
修正《啊哈算法》上模拟链表算法的错误相关推荐
- 已知一个带有表头的单链表,结点结构为data-link,假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。
今天和大家分享一道2009年代码为408的一道真题: 已知一个带有表头的单链表,结点结构为data-link,假设该链表只给出了头指针list.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链 ...
- 操作系统课设之虚拟内存页面置换算法的模拟与实现
前言 课程设计开始了,实验很有意思,写博客总结学到的知识 白嫖容易,创作不易,学到东西才是真 本文原创,创作不易,转载请注明!!! 本文链接 个人博客:https://ronglin.fun/arch ...
- 操作系统学习之用C语言模拟LRU算法
前言 LRU算比较经典,而且考的也比较多,LRU算法全称Least Recently Used,译为最近最少使用.用C模拟一下吧. Buddy算法:操作系统学习之用C语言模拟伙伴(Buddy)算法 F ...
- 基于自适应算法和增量式PID算法的模拟直升飞机控制系统
基于自适应算法和增量式PID算法的模拟直升飞机控制系统 文章目录 基于自适应算法和增量式PID算法的模拟直升飞机控制系统 控制系统硬件 单片机系统 传感器系统介绍 直升机模拟系统介绍 系统模块介绍 A ...
- 用循环首次适应算法、最佳适应算法和最坏适应算法,模拟可变分区存储管理,实现对内存区的分配和回收管理
湖南师范大学 信息科学与工程学院 操作系统课程实验报告 实验项目名称: 可变分区存储管理 题目 实验一.可变分区存储管理 一.实验目的: 加深对可变分区存储管理的理解: 提高用C语言编制大型系统程序的 ...
- 41. 盘点那些必问的数据结构算法题之链表
盘点那些必问的数据结构算法题之链表 0 概述 1 定义 2 基本操作 3 链表相关面试题 3.1 链表逆序 3.2 链表复制 3.3 链表合并 3.4 链表相交判断 3.5 判断链表是否存在环 3.6 ...
- 【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)
一.线性表 1.1 概念与特点 1.2 线性表的存储结构 1.3 常见操作 1.4 应用场景 二.链表 2.1 链表简介 2.2 单向链表(单链表) 2.21 基本概念 2.22 单链表基本操作 2. ...
- 操作系统: 最佳适配算法和邻近适配算法的模拟实现(内存分配算法)
实现动态分区的分配算法. (1) 最佳适配算法:选择内存空闲块中最适合进程大小的块分配. (2) 邻近适配算法:从上一次分配的地址开始查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程. ...
- 为了OFFER,花了几个小时,刷下Leetcode链表算法题
@Author:Runsen @Date:2020/9/13 链表是我这辈子的痛啊,每次学到链表,就往往不会,就没有继续学下去.现在大四不能继续让这个链表阻碍我了.现在基本是重刷数据结构和算法,毕竟笔 ...
最新文章
- DR模式 mysqlABB读写分离
- laytpl遍历实体列表_Layui数据表格之获取表格中所有的数据方法
- 个人项目耗时对比记录表
- 去除dataframe中的空行_Word中这些一键操作实在太强了!折腾半天的工作,一秒就能搞定!...
- Python 学习 DAY1
- java mongo分组统计_mongodb 分组 topN
- 成为JavaGC专家Part I — 深入浅出Java垃圾回收机制
- 在Carmaker中建立自己的交通环境
- phpstudy安装及简单使用教程
- sql2012下载,安装,激活
- SYNOPSYS™光学设计软件---设计自由曲面反射系统
- EPLAN2.9程序安装及注意事项
- Ubuntu 18安装搜狗拼音
- 基于ssm与maven,使用easyui--tree生成类似部门管理树形结构图
- linux 查看 man 路径配置文件 man.config,linux中的man(zz)
- mysql (1205, 'Lock wait timeout exceeded; try restarting transaction')
- 项目管理第十三章项目相关方管理
- win7删除系统自带中文简体输入法中美式键盘
- mongodb 配置文件解读
- 智能巡检机器人的“顺风耳、千里眼、金钟罩”
热门文章
- Android 9.0 MTK平台 修改热点自动关闭功能(保持热点打开)
- HTML#4(Vue3)
- 活了20年多了才知道!蜂蜜十大鲜见真相吓掉小命
- iOS之NSData和字节学习
- Wordpress漏洞,WPScan使用完整攻略
- #记录一下:关于三维建图的一些文章讲解 + Delaunay三角剖分的含义
- 微信公众号【阿里技术(ali_tech)】历史文章整理
- pytorch深度学习案例(二)——航拍街道语义分割
- cctalk录屏翻录工具使用教程
- (十)pytorch学习笔记---内容为学习资源摘录整合の梯度下降方法--Adadelta(5)