• 堆栈


    2. 堆栈 

    我们已经对堆栈这种数据结构有了初步认识。堆栈是一组元素的集合,类似于数组,不同之处在于,数组可以按下标随机访问,这次访问a[5]下次可以访问a[1],但是堆栈的访问规则被限制为Push和Pop两种操作,Push(入栈或压栈)向栈顶添加元素,Pop(出栈或弹出)则取出当前栈顶的元素,也就是说,只能访问栈顶元素而不能访问栈中其它元素。如果所有元素的类型相同,堆栈的存储也可以用数组来实现,访问操作可以通过函数接口提供。看以下的示例程序。

    例 12.1. 用堆栈实现倒序打印

    #include <stdio.h>
    
    char stack[512];
    int top = 0;
    
    void push(char c)
    {
    	stack[top++] = c;
    }
    
    char pop(void)
    {
    	return stack[--top];
    }
    
    int is_empty(void)
    {
    	return top == 0;
    }
    
    int main(void)
    {
    	push('a');
    	push('b');
    	push('c');
    	
    	while(!is_empty())
    		putchar(pop());
    	putchar('\n');
    
    	return 0;
    }

    运行结果是cba。运行过程图示如下:

    图 12.1. 用堆栈实现倒序打印

    用堆栈实现倒序打印

    数组stack是堆栈的存储空间,变量top总是保存数组中栈顶的下一个元素的下标,我们说“top总是指向栈顶的下一个元素”,或者把top叫做栈顶指针(Pointer)。可以用它检验循环的正确性,这里的“top总是指向栈顶的下一个元素”其实也是一种Invariant,Push和Pop操作总是维持这个条件不变,这种Invariant描述的对象是一个数据结构而不是一个循环,在DbC中称为Class Invariant。Pop操作的语义是取出栈顶元素,但上例的实现其实并没有清除原来的栈顶元素,只是把top指针移动了一下,原来的栈顶元素仍然存在那里,这就足够了,因为此后通过Push和Pop操作不可能再访问到已经取出的元素,下次Push操作就会覆盖它。putchar函数的作用是把一个字符打印到屏幕上,和printf%c作用相同。布尔函数is_empty的作用是防止Pop操作访问越界。这里我们预留了足够大的栈空间(512个元素),其实严格来说Push操作之前也应该检查栈是否满了。

    main函数中,入栈的顺序是'a''b''c',而出栈打印的顺序却是'c''b''a',最后入栈的'c'最早出来,因此堆栈这种数据结构的特点可以概括为LIFO(Last In First Out,后进先出)。我们也可以写一个递归函数做倒序打印,利用函数调用的栈帧实现后进先出:

    例 12.2. 用递归实现倒序打印

    #include <stdio.h>
    #define LEN 3
    
    char buf[LEN]={'a', 'b', 'c'};
    
    void print_backward(int pos)
    {
         if(pos == LEN)
    	  return;
         print_backward(pos+1);
         putchar(buf[pos]);
    }
    
    int main(void)
    {
         print_backward(0);
         putchar('\n');
         
         return 0;
    }

    也许你会说,又是堆栈又是递归的,倒序打印一个数组犯得着这么大动干戈吗?写一个简单的循环不就行了:

    for (i = LEN-1; i >= 0; i--)
    	putchar(buf[i]);

    对于数组来说确实没必要搞这么复杂,因为数组既可以从前向后访问也可以从后向前访问,甚至可以随机访问,但有些数据结构的访问并没有这么自由

  • 相关阅读:
    git下载指定的版本
    QT中定时器
    makefile 中添加依赖的库文件
    Qt 出现“undefined reference to `vtable for”
    qt程序启动播放动画
    常用正则表达式
    当你纠结时,请打开这31个锦…
    android mk详解
    C++日志系统log4cxx使用总结
    qt 坐标变换
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2994065.html
Copyright © 2020-2023  润新知