热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

栈:装水的杯子(一)入门测试题

子渊学算法之——栈:装水的杯子(一)入门测试题首先来介绍我们的主人公:梁子渊,男,12岁,小学六年级学生。子渊参加了计算
 

子渊学算法之

——栈:装水的杯子

 

(一)入门测试题

 

首先来介绍我们的主人公:梁子渊,男,12岁,小学六年级学生。

子渊参加了计算机程序设计兴趣小组,学了一个学期的PASCAL语言和简单的组合数学知识,想要向更高级的技术——数据结构和算法发起挑战了。正巧爸爸也是一个算法迷,于是两父子展开了以下的对话:

       “爸爸,我想学习数据结构和算法,老师说掌握它们就可以在计算机的天地里畅通无阻了。爸爸你快教教我吧!”

       “是吗?那你基础打得怎么样了?让我先来考考你,看看你有没有学习算法的潜质。”

“好啊!尽管放马过来吧——只是题目不要太难。”

“你放心,绝对基础题!”

题目:输入一个正整数n,试分离并输出其各位数字。例如,输入n=1234,则输出1234。(保证n不超出integer的范围)

子渊一看题目心里就乐了,这么简单啊!我刚学习PASCAL语言的时候就做过这种题目了,不就是考查整除和取余运算吗?

不到三分钟,子渊就把代码交到了爸爸手里:

{代码1}

{输入一个正整数n,试分离并输出其各位数字}

PROGRAM Separate(INPUT, OUTPUT);

VAR

    v, n : integer;

 

BEGIN {MAIN}

    writeln('Input n:');

    readln(n);

 

    while n <> 0 do

    begin

        v := n mod 10; {分离出n的个位数字}

        write(v:2);

        n := n div 10; {去除n的个位数字}

    end; {while}

END.

爸爸看了代码以后,点了点头,说:“不错不错,代码风格不错!结构整齐,注释完整,基本功还可以。可惜啊!没按题目要求来做。”

子渊一听就急了,“怎么没按题目要求做?我不是从低位到高位把n的各位数字都分离并输出来了吗?”

“你把n的各位数字从低位到高位都分离了是不错,可是你的输出顺序也是从低位到高位,这不符合题目要求,也与我们的书写习惯不同啊。”

“对喔!我刚好弄反了。”子渊这才不会意思的挠了挠脑袋,“这该怎么办呢?”

“再好好想想!如果给定的正整数n是个3位数呢?”爸爸提示道。

3位数?那很好办啊!只要从高位开始分离数字就好了。”子渊兴奋得跳了起来,“也就是说,我只要先判断出n是个几位数,从高位开始分离数字就好了,因为保证n不超出integer的范围(HIGH(integer) = 32767),所以它至多是个5位整数,这样我至多判断5次就可以知道n是个几位数了。”

不一会儿,新的代码又交到了爸爸的手里:

{代码2}

{先判断出n是个几位数,再从高位开始分离数字并输出}

PROGRAM Separate(INPUT, OUTPUT);

VAR

    v, n, h : integer;

 

FUNCTION Highest(n : integer) : integer; {判断n是个几位数,最大为32767}

begin

    if n > 10000 then

        Highest := 10000

    else if n > 1000 then

        Highest := 1000

    else if n > 100 then

        Highest := 100

    else if n > 10 then

        Highest := 10

    else

        Highest := 1;

end; {Highest}

 

BEGIN {MAIN}

    writeln('Input n:');

    readln(n);

 

    h := Highest(n); {判断n是个几位数}

    while h <> 0 do {分离数字并将其入栈}

    begin

        v := n div h; {分离出n的最高位数字}

        write(v:2);

        n := n mod h; {去除n的最高位数字}

        h := h div 10;{n位数降1}

    end; {while}

END.

“不错,确实能实现我所要求的功能,反应挺快!可是你不觉的这次的代码很“丑陋”吗?你看,姿态臃肿,一点也不简洁。特别是那个Highest()函数,只能用来判断integer类型数据,通用性很差。我们编写代码也是要讲究美感的啊!”爸爸稍微点了点头就马上叹起气来。

“很丑陋?我怎么没感觉到啊!它不是很好地实现了我们的意图吗?”子渊很是不解。

“实现了所需要的功能不错,可是这种实现的方法不够简洁,美观,缺乏通用性。反正我看着就是不顺眼——就像你这乱七八糟的书桌一样。”话说着,爸爸就帮子渊整理起书桌来:他把摆放得杂乱无章的各种童话,围棋和自然科学书籍一一收起来,放到一旁的储物箱里。

“其实你最初从低位开始分离数字的思路是正确的,因为这样不用事先判断n是个几位数,所以很容易实现。但是你把数字一分离出来就马上输出是不对的,最先分离出的数字是不能最早输出的。”

“最先分离的数字不能最早输出?那我该怎么办呢?”子渊喃喃自语。

“——咦,我的那本《科幻大王》呢?就是放在桌子最上面那本,爸爸你把它弄哪里去了?我还没看完呢!”子渊突然发现自己书桌上的书都不见了,马上嚷嚷起来。

“你嚷嚷什么呀!那些书我都收起来了,全部放在储物箱里。那本《科幻大王》是我最先收起来的,应该在箱子的底部,你自己去拿吧。”

“爸爸你真爱作弄人啊,把它放在最下面了!那我不是要把其他的书都移开才能拿到吗?真麻烦!”

“是啊,最早放进去的书自然是最后拿出来了!”爸爸顺口回答,“其实生活中类似这样的情况还真不少呢,比如你妈妈换蜂窝煤的时候,最先放进去的煤块不也是最后被拿出来吗?”

“我知道我知道!还有杂技演员表演叠罗汉的时候,最后上去的人总是第一个下来。”子渊也不甘示弱地补充。

“是啊,还有我们喝水的时候,最先喝到的总是最上层的水,而它们是最后被倒进去的。”爸爸继续补充,“计算机科学家们还给这种操作特点取了一个优雅的名字——“后进先出”呢。”

“后进先出?”

“是啊,上面所有的例子,不都体现了“后进先出”的特点吗?”

“可是,计算机科学家们为什么要研究它们啊?还给它取一个这么奇怪的名字。”子渊还是不明白爸爸说这些话有什么意思。

““后进先出”(LAST IN FIRST OUT,简称LIFO)只是它的特点,其实这是计算机程序设计中一个常见的数据结构——栈(STACK),它是一种存储数据的容器,就像装水的杯子一样。”爸爸进一步解释,“水杯里的水按照“后进先出”的顺序被倒进倒出,存储在栈中数据也是是按照“后进先出”的方式被插入和删除的。”

“原来是这样啊!”子渊好像明白了些什么,但还是有很多的疑问,“可是这样的数据结构有什么作用呢?”

“要知道栈有什么用途,首先我们要搞清楚它本身的属性和能够实现的基本操作。子渊你想想看,这个像装水的杯子一样的数据容器——栈,它应该具备哪些属性和进行哪些操作呢?”

“存储数据的容器,像装水的杯子一样。。。。。嗯!那它应该可以插入和删除数据。对了,栈用什么来装这些数据啊?”子渊的问题就像水里的气泡一样不断地往外冒。

“栈可不是什么天外来客,它建立在各种程序设计语言的原有数据类型的基础上,比如PASCAL语言,我们可以用内置的数组或链表数据类型来实现栈结构。”爸爸解释道,“那你知道该如何用数组来实现栈的基本属性和操作吗?先考虑栈的属性,它具有哪些基本属性呢?”

“栈的属性?像装水的杯子一样的栈?首先应该要有一个容量属性吧,比如杯子的容量有200ML500ML等。”子渊回答。

“确实是这样!但不止这一个。实际上栈有三个基本属性:最大容量(最大高度),实际存储量(实际高度),栈空指示标志。计算机科学家用“栈顶”来指示栈的实际高度,用“栈底”来作为栈空指示标志。当栈顶和栈底指向同一位置时,表示栈内没有存储元素,即栈为空。”

“这样啊!那栈的基本操作是不是删除和插入元素呢?”

“不错,这正是栈最基本的操作,就像杯子可以用来装水和倒水一样。需要注意的是,正如杯子的装水和倒水动作都是在最上层的水面进行,栈的插入和删除操作也只能在栈顶进行。我们称插入操作为入栈或进栈,而删除操作为出栈或退栈。”爸爸回答道,“那么,我们是不是只需要这两种基本操作就行了呢?”

“还有别的?那会是什么操作呢?”子渊陷入了沉思。

“子渊,你想想看,我们在往杯子里加水的时候是不是一直不停地加啊?”爸爸又给出了提示。

“啊?不是啊!杯子满了就不能再加了。对了,我们还要做一个判断栈满的操作。”

“还有呢?”

“往里加水的时候要判断栈满,那往外倒水的时候就应该判断栈空了——我们还要做一个判断栈空的操作。”

“不错,能够触类旁通,脑子转得挺快的啊!另外,我们并不是一拿到杯子就要喝水,有些时候我们只是想看看杯子里面的水干不干净,并不一定要往外倒水。这也可以看成是一个基本操作:获取栈顶元素的值。”

“栈顶元素?”

“是啊,我们把栈顶所指的元素称为栈顶元素。”

“原来是这样啊!那栈这种数据结构就是有三个基本属性和五个基本操作了咯?”

“正确。现在就请你写出实现它的PASCAL代码吧。”爸爸又交代了任务,“顺便说一句,那个分离数字的问题用栈可以很漂亮地解决。”

十分钟过去了。。。。。。

子渊在电脑里写出代码,并且编译通过,赶紧把爸爸拉过来请他检查。

下面是代码:

{代码3}

{利用栈解决分离数字问题:输入一个正整数n,试分离并输出其各位数字}

PROGRAM Separate(INPUT, OUTPUT);

CONST

    MAXCAPACITY = 100; {栈的最大容量}

    BOTTOM = 0;        {栈底标志}

     

TYPE

    ElemType = integer;  {栈内元素数据类型}

    Stack    = array [1..MAXCAPACITY] of ElemType; {用数组表示的栈}

 

VAR

    s    : Stack;       {定义s为栈}

    top  : integer;     {栈顶标志}

    v, n : integer;

 

FUNCTION StackEmpty(s : Stack; top : integer) : boolean; {判断是否栈空}

begin

    StackEmpty := (top = BOTTOM);

end; {StackEmpty}

   

FUNCTION StackFull(s : Stack; top : integer) : boolean; {判断是否栈满}

begin

    StackFull := (top = MAXCAPACITY);

end; {StackFull}

   

FUNCTION GetTop(s : Stack; top : integer)  : ElemType; {获取栈顶元素的值}

begin

    if StackEmpty(s, top) then

        writeln('underflow')

    else

        GetTop := s[top];

end; {GetTop}

 

PROCEDURE Push(var s : Stack; var top : integer; data : ElemType); {入栈}

begin

    if StackFull(s, top) then

        writeln('overflow')

    else

    begin

        inc(top);

        s[top] := data;

    end; {if}

end; {Push}

   

PROCEDURE Pop(var s : Stack; var top : integer) ; {出栈}

begin

    if StackEmpty(s, top) then

        writeln('underflow')

    else

        dec(top);

end; {Pop}

   

BEGIN {MAIN}

    top := 0; {栈顶初始化}

 

    writeln('Input n:');

    readln(n);

   

    while n <> 0 do {分离数字并将其入栈}

    begin

        v := n mod 10; {分离出n的个位数字}

        Push(s, top, v);      {个位数字入栈}

        n := n div 10; {去除n的个位数字}

    end; {while}

   

    while not StackEmpty(s, top) do {输出数字并出栈}

    begin

        write(GetTop(s, top) : 2);

        Pop(s, top);

    end; {while}

END.

 

爸爸终于笑了,子渊长长地舒出一口气——考试通过咯。

 


推荐阅读
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
author-avatar
江湖小子的美好生活_498_416
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有