栈之顺序栈

来源:互联网 发布:淘宝店标制作网站 编辑:程序博客网 时间:2024/05/22 11:41

目录

  1. 顺序栈的简介
  2. 举例以及详细分析
  3. 代码块
  4. 测试结果

顺序栈的简介

在顺序栈中有”上溢”和”下溢”的概念。顺序栈好比一个盒子,我们在里头放了一叠书,当我们要用书的话只能从第一本开始拿(你会把盒子翻过来吗?真聪明^^),那么当我们把书本放到这个栈中超过盒子的顶部时就放不下了(叠上去的不算,哼哼),这时就是”上溢”,”上溢”也就是栈顶指针指出栈的外面,显然是出错了。反之,当栈中已没有书时,我们再去拿,看看没书,把盒子拎起来看看盒底,还是没有,这就是”下溢”。”下溢”本身可以表示栈为空栈,因此可以用它来作为控制转移的条件。


举例以及详细分析

栈是仅限定在表尾进行插入和删除操作的线性表,共定义了九种栈的基本操作:分别是构造 销毁 清空 栈长 栈顶 插入 删除 遍历。

在下面压栈代码中,会用到realloc函数:void * realloc ( void * ptr, size_t new_size );
就是在原有内存上再申请一块内存!
关于realloc的行为方式,结合源码总结为:
1. realloc失败的时候,返回NULL;

  1. realloc失败的时候,原来的内存不改变,也就是不free或不move,(这个地方很容易出错);

  2. 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址;

  3. 如果size为0,效果等同于free();

  4. 传递给realloc的指针可以为空,等同于malloc;

  5. 传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的。


代码块

#include <stdio.h>  #include<stdlib.h>#include <malloc.h>//int *p p只能是是地址 *p是值,指针是用来存储值的地址typedef int SElemType;typedef int Status;#define INIT_SIZE 100  #define STACKINCREMENT 10  #define Ok 1  #define Error 0  #define True 1  #define False 0  typedef struct{    SElemType *base;    SElemType *top;    int stacksize;}SqStack;//初始化栈  Status InitStack(SqStack *s){    s->base = (SElemType *)malloc(INIT_SIZE * sizeof(SElemType));    if (!s->base)    {        puts("存储空间分配失败!");        return Error;    }    s->top = s->base;    s->stacksize = INIT_SIZE;    return Ok;}//清空栈  Status ClearStack(SqStack *s){    s->top = s->base;    return Ok;}//栈是否为空  Status StackEmpty(SqStack *s){    if (s->top == s->base)        return True;    else        return False;}//销毁栈  Status Destroy(SqStack *s){    free(s->base);    s->base = NULL;    s->top = NULL;    s->stacksize = 0;    return Ok;}//获得栈顶元素  //Status GetTop(SqStack *s, SElemType &e)//{//  if (s->top == s->base) return Error;//  e = *(s->top - 1);//  return Ok;//}//压栈  Status Push(SqStack *s, SElemType e){    if (s->top - s->base >= s->stacksize)//栈满      {        s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREMENT) * sizeof(SElemType));        //这次申请的内存是以s->base为起始点的内存,但是s->base的位置有可能发生变化,这里是多分配了STACKINCREMENT个SElemType        if (!s->base)        {            puts("存储空间分配失败!");            return Error;        }        s->top = s->base + s->stacksize;//修改栈顶位置          s->stacksize += STACKINCREMENT;//修改栈长度      }    *s->top++ = e;    return Ok;}//弹栈  Status Pop(SqStack *s, SElemType *e){    if (s->top == s->base) return Error;    s->top--;//因为在插入的时候为*s->top++=e,最后一次入栈完成后,top指针还会加1,最后top指针指向的并不是栈顶元素而是栈顶元素上面的空间,因此要--    *e = *(s->top);    return Ok;}//遍历栈  Status StackTraverse(SqStack *s){    SElemType *b = s->base;//此处不能直接用base或top移动,即不能改变原栈的结构      SElemType *t = s->top;    while (t > b)        printf("%d ", *b++);    printf("\n");    return Ok;}//Status visit(SElemType c)//{//  printf("%d ", c);//  return Ok;//}int main(){    SqStack a;    SqStack *s = &a;    SElemType e;    InitStack(s);    int n;    puts("请输入要进栈的个数:");    scanf("%d", &n);    while (n--)    {        int m;        scanf("%d", &m);        Push(s, m);    }    /*e = GetTop(s, e);*/    StackTraverse(s);    puts("");    puts("8进栈后:");    Push(s, 8);    StackTraverse(s);    puts("");    Pop(s, &e);    printf("出栈的元素是:%d\n", e);    printf("元素出栈后事实上并没有清除,依然存在于内存空间,所谓的出栈只是指针移动,出栈的元素是%d\n", *s->top);//判断出栈后元素是否还存在于内存中      StackTraverse(s);    Destroy(s);    system("pause");    return 0;}

测试结果

这里写图片描述

0 0
原创粉丝点击