戳一戳!和我一起走进信息学的世界
导读
信息学能够有助于孩子未来工作发展,提升孩子的综合能力。
这一期课,我们承上启下,简单复习信息学所有C++的知识体系,讲解一部分初赛和复赛的知识;然后就从顺序表和链表,开始一步一步走进数据结构的世界!
这一节课,我们来分析顺序表的缺点,讲解一个新的数据结构——链表,并做一些链表的实训,分析一道信息学初赛的真题。让我们一起走进今天的文章吧!
往期回顾
【NOIP竞赛/CSP认证】
▶ 赛前必看!信息学名师带你复习NOIP竞赛初赛及CSP认证初赛
【信息学精华帖】
▶ 收藏!交流会内容全公开,让你陪孩子更好地学习信息学
▶ 信息学提高班知识体系详解与家长常见问题解答!让孩子赢在提高班学习的起跑线!
【数据结构前导课】
▶ 1 温故知新——一篇文章领略信息学C++知识结构
▶ 3 运筹帷幄——一篇文章,让指针学起来也很简单!
【C++提高班教程】
▶ C++强化 | 02 继续前行,三大结构终极介绍
▶ C++强化 | 09 一篇文章带你探索函数的奥秘
【C++基础班教程】
▶ C++总结 | 11 开关语句switch-case
▶ C++总结 | 14 break与continue
▶ C++总结 | 15 while与do-while
1 顺序表分析
前面两节课,我们学习了顺序表!我们一起来简单复习一下顺序表,再分析一下顺序表的缺点。
1 顺序表复习
顺序表是用一组地址连续的存储单元,依次存储线性表中的数据元素,从而使逻辑上相邻的两个元素在物理位置上也相邻。
经过上面两次课,我们也知道,顺序表中的元素,可以通过索引去访问。
2 顺序表的缺点
顺序表使用起来比较简单,那它是百分百完美的吗?
当然不是,我们在写顺序表的函数的时候,应该会注意到一个问题,如果我们想在中间插入或者删除一个数据,这个位置的后面的数据都要后移或者前移。
也就是说顺序表插入或者删除数据,可能需要移动大量元素。
2 玩个游戏
我们一起来看一个小游戏。
1 母鸡与小鸡
母鸡带着小鸡出去买东西,为了防止黄鼠狼带走小鸡,母鸡就让小鸡一个接一个地走在自己的后面,每个小鸡,要记住自己身后的小鸡,母鸡要记住身后第一只小鸡。
一旦黄鼠狼抓走了某一只小鸡,母鸡就知道谁被抓走了,这只小鸡就要重新记住一只新的小鸡。
2 鸡妈妈与小鸡分析
假如,母鸡为A,小鸡有名字为b,c,d,e,f,g;
现在有一只新的小鸡h加进来,站到c和d中间,c小鸡就要重新记住身后的小鸡是h,h要记住身后的小鸡是d。
这个时候,母鸡想要找到小鸡f,就可以按照如下方式:
现在我们用箭头表示小鸡b能够找到小鸡c:
那么我们就可以得到如下的序列:
3 链表
上面的这个流程,就是链表的流程,我们一起来学习一下链表。
1 链式存储结构
我们先来讲一下链式存储结构。
我们可以用一条链将所有的数据连在一起,可以通过链让某一个数据找到它的下一个数据,通过不断找下一个数据的这种方式,我们就可以找到链上的任意一个数据。
上面的就是链式结构的示意图。我们发现:每一个数据块通过一个箭头相互连接,所有的数据不用像顺序表一样必须排列在一起。
链式存储结构即用一组任意的存储单元存储线性表的数据元素(这组存储单元可以连续,也可以不连续)。我们还需要使用箭头指向它的下一个数据。在C++中,我们使用指针的方式,来指向其下一个数据的地址。这个时候,我们存放数据,还需要存一个指针。
2 什么是链表
多个节点,使用指针一一连接成一个串(链),这个链就是链表。
一个简单的链表,至少需要两部分变量,一个是存放其数据的变量,另一个是存放其下一个数据的指针变量。
也就是说。一个链表的结构如下:
其中ABCD表示的是数据,箭头表示的是指针,^ 表示后继没有数据,所以为空。
3 定义一个单链表
根据上面的内容,我们就可以定义一个链表:
4 定义一个双向链表
双向也是一种链表,双向链表有两个指针,一个指针指向它的左边的数据,一个指针指向它的右边的数据。
上面就是一个双向链表的示意图,l(left)表示指向其左边数据的指针,r(right)表示指向其右边数据的指针。
所以我们可以定义双向链表结构如下:
3 链表必备操作
前面我们定义了单链表和双向链表,接下来我们一起来看一下信息学中会考到的几个必备操作。
这里大家重点理解逻辑,链表到目前为止,只在信息学提高组初赛中以选择题的形式出现过。所以我们这里也只讲和竞赛相关的。
如果大家有兴趣想更加深入了解顺序表和链表,可以看下面这两篇文章:
对于链表来说最重要的是要理解链表的插入和删除操作,这是因为,链表的插入元素和删除元素只需要给修改对应指针即可,不需要移动元素位置。
1 单链表插入元素
以下面的为例:
也就是下图:
我们需要让b的next指针指向e,让e的next 指针指向c,让b指向c的指针断开。
所以我们需要下面流程:
代码如下:
上面是最简单的情况,如果我们想实现,在b的后面插入一个数据,但是我们不知道原表中b的后面是c,这个时候,如果我们还是先写下面的语句:
b原本后面的就找不到了,所以,我们要先让插入的结点指向b的next,然后再让b指向新插入的结点。
代码如下:
2 单链表删除元素
最简单的是删除结点b的后一个结点。
图示如下:
代码如下:
接下来是:已知结点b的前一个结点是a,删除结点b。
代码如下:
3 双向链表插入元素
对于双向链表,我们来看一道信息学竞赛题目:
对于选项A,太过着急让pq相连,就找不到p本来的左边。如下图,我们假设P的左边是m,我们先连接pq那么q和m就无法连接,所以A不对。
对于B,第三条语句让q的右边为p,p的左边应该为q,而不是q的右。如果按照它的做法,p的左边就指向自身。图示如下:
对于C,让p的右为q,就破坏了原本的链表,q是插在p的左边,而不是右边。
通过以上分析我们已经能知道D就是正确选项了,我们来一起通过图示看一下D选项:
这个解法不唯一,还可以有很多其他做法,例如:
对应代码为:
图示如下:
5 作业
本节课的作业,就是复习上面的所有知识,并完成下面的题目!
1 NOIP2014年提高组
单项选择题,选择错误的一项,并说明理由:
AI与区块链技术
长按二维码关注