堆栈的操作过程,堆栈溢出

  堆栈的操作过程,堆栈溢出

  我们对栈的数据结构有了初步的了解。堆栈是元素的集合,类似于数组,只是数组可以通过下标随机访问。这次访问a[5]下次可以访问a[1],但是栈的访问规则仅限于Push和Pop操作。Push (Push或push)将元素添加到堆栈的顶部,而Pop (pop或Pop)则取出当前堆栈顶部的元素,即只能访问顶部的元素,不能访问顶部的元素。如果所有元素都是同一类型,那么栈的存储也可以用数组来实现,访问操作可以通过函数接口来提供。请看下面的示例程序。

  例12.1。堆叠反转打印

  #包含stdio.h

  字符堆栈[512];

  int top=0;

  无效推送(字符c)

  stack[top]=c;

  字符弹出(无效)

  返回堆栈[-top];

  int是_empty(void)

  return top==0;

  int main(void)

  push( a );

  推( b );

  push( c );

  而(!is_empty())

  putchar(pop());

  putchar( n );

  返回0;

  }

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

  在主函数中,堆栈的顺序是 a , b , c ,而打印出堆栈的顺序是 c , b , a ,最后一个 c 先出来,所以堆栈的这种数据结构的特点可以概括为LIFO(后进先出)。我们也可以写一个递归函数逆序打印,利用函数调用的堆栈框架实现LIFO:

  例12.2。递归反向打印

  #包含stdio.h

  #定义镜头3

  char buf[LEN]={a , b , c };

  void print_backward(int pos)

  if(pos==LEN)

  返回;

  向后打印(位置1);

  putchar(buf[pos]);

  int main(void)

  print _ backward(0);

  putchar( n );

  返回0;

  }

  你可能会说,堆栈和递归,逆序打印一个数组值得吗?只需编写一个简单的循环:

  for(I=LEN-1;我我-)

  putchar(buf[I]);

  对于数组来说真的没必要这么复杂,因为数组可以从前到后,从后到前,甚至随机访问,但是有些数据结构就没那么自由访问了。

堆栈的操作过程,堆栈溢出