zoukankan      html  css  js  c++  java
  • 顺序栈的基本操作(C语言)

      由于现在只学了C语言所以就写这个C语言版的栈的基本操作

    这里说一下 :网上和书上都有这种写法 int InitStack(SqStack &p)

    &p是取地址  但是这种用法好像C并不支持 ,C++才支持,所以用

    C语言写就需要使用指针

    代码如下:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #define STACK_INIT_SIZE 100//储存空间初始分配量
      4 #define STACKINCREMENT  10//存储空间分配增量
      5 #define OK 1
      6 #define ERROR 0
      7 typedef int StackType; //栈元素类型
      8  
      9 typedef struct {
     10     StackType *base;   //在构造之前和销毁之后,base的值为NULL
     11     StackType *top;    //栈顶指针
     12     int stacksize;     //当前已分配的存储空间,以元素为单位
     13 }SqStack; //顺序栈
     14 
     15 //栈的初始化
     16 int InitStack(SqStack *p) {
     17     
     18     
     19     p->base = (StackType*)malloc(STACK_INIT_SIZE * sizeof(StackType));
     20     if (p->base == NULL)  return ERROR;  //内存分配失败
     21     p->top = p->base;     //栈顶与栈底相同表示一个空栈
     22     p->stacksize = STACK_INIT_SIZE;
     23     return OK;
     24 
     25 }
     26 //判断栈是否为空
     27 int EmptyStack(SqStack *p) {
     28     //若为空栈 则返回OK,否则返回ERROR
     29     if (p->top == p->base) return OK;
     30     else return ERROR;
     31 }
     32 //顺序栈的压入
     33 int Push(SqStack *p,StackType e) {
     34     //插入元素e为新的栈顶元素
     35     if ((p->top - p->base)>= p->stacksize)   //栈满,追加储存空间
     36     {
     37         p->base = (StackType*)realloc(p->base, (p->stacksize + STACKINCREMENT) * sizeof(StackType));
     38         if (p->base == NULL)   return ERROR;// 储存空间分配失败
     39         p->top = p->base + p->stacksize;    //可能有人觉得这句有点多余(我当时也是这么想的 后面有解释)
     40         p->stacksize += STACKINCREMENT;
     41     }
     42     *(p->top) = e;
     43     (p->top)++;
     44     return OK;
     45 }
     46  // 顺序栈的弹出     
     47 int Pop(SqStack *p,StackType *e) {
     48     //若栈不空,则删除p的栈顶元素,用e返回其值
     49     if (p->top == p->base) return ERROR;
     50     --(p->top);
     51     *e = *(p->top);
     52     return OK;
     53     
     54 
     55 }
     56 //顺序栈的销毁
     57 int DestroyStack(SqStack *p) {
     58     //释放栈底空间并置空
     59         free(p->base);
     60         p->base = NULL;
     61         p->top = NULL;
     62         p->stacksize = 0;
     63         
     64         return OK;
     65 }
     66 //将顺序栈置空 栈还是存在的,栈中的元素也存在,如果有栈中元素的地址任然能调用
     67 int ClearStack(SqStack *p) {
     68     p->top= p->base;
     69     return OK;
     70 }
     71 //返回顺序栈的元素个数
     72 int StackLength(SqStack p) {
     73     //栈顶指针减去栈底指针等于长度,因为栈顶指针指向当前栈顶元素的下一个位置
     74     return p.top - p.base;
     75 }
     76 //返回顺序栈的栈顶元素
     77 int GetTop(SqStack *p, StackType *e) {
     78     //若栈不为空,则用e返回p的栈顶元素
     79     if (p->top > p->base) {
     80         *e = *(p->top - 1); return OK;
     81     }
     82     else return ERROR;
     83 }
     84 //从栈顶到栈底对每个元素调用某个函数
     85 int StackTraverse(SqStack p,void (*pfun)(StackType)/*函数指针*/){
     86 //从栈底到栈顶依次对栈中的每个元素调用函数pfun()
     87     while (p.top > p.base)
     88     pfun(*(p.base)++);                //先调用后递增
     89     printf("
    ");
     90     return OK;
     91 }
     92 //打印栈中元素
     93 void print(StackType stack) {
     94     printf("%d
    ", stack);
     95     
     96 }
     97 //测试栈的各种操作
     98 int main() {
     99     int n,i;
    100     StackType *e,a;
    101     SqStack *pstack,stack;
    102     pstack = &stack;
    103     e=(StackType*)malloc(sizeof(StackType));    //为指针e分配内存地址
    104     InitStack(pstack);                            //初始化栈
    105 
    106     if (EmptyStack(pstack) == 1) printf("-------栈为空-------
    ");
    107     printf("请输入栈的元素个数:");
    108     scanf("%d", &n);
    109     for (i = 0; i < n; i++)
    110     {
    111         scanf("%d", &a);
    112         Push(pstack, a);
    113     }
    114     if (EmptyStack(pstack) == 0) printf("-------栈不为空-----
    ");
    115         
    116     printf("栈的长度为:%d
    ", StackLength(stack));
    117     printf("--------------------
    ");
    118     printf("请输入一个入栈元素:");
    119     scanf("%d", &a);
    120     Push(pstack, a);
    121     printf("--------------------
    ");
    122     printf("栈中的元素个数为:%d
    ", StackLength(stack));
    123     printf("--------------------
    ");
    124     GetTop(pstack, e);
    125     printf("栈顶元素为:%d
    ", *e);
    126     printf("--------------------
    ");
    127     printf("打印栈中的元素:
    ");
    128     StackTraverse(stack, print);
    129     printf("---弹出栈顶元素---
    ");
    130     Pop(pstack, e);
    131     printf("弹出的栈顶元素为:%d
    ", *e);
    132     printf("--------------------
    ");
    133     GetTop(pstack, e);
    134     printf("栈顶元素为:%d
    ", *e);
    135     printf("--------------------
    ");
    136     printf("打印栈中的元素:
    ");
    137     StackTraverse(stack, print);
    138     printf("--------------------
    ");
    139 
    140     printf("----------清空栈-------
    ");
    141     if (ClearStack(pstack) == 0)  printf("已清空栈
    ");
    142     
    143     printf("----------销毁栈-------
    ");
    144     if (DestroyStack(pstack) == 0)  printf("已销毁栈
    ");
    145     return 0;
    146    
    147 }
        

     

          第39行  p->top = p->base + p->stacksize;这句有必要加上吗?  答案是肯定的。
            这一个问题的关键在于 realloc 是怎么实现的,有两种情况:

       如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address。
     这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时,
    realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。
     也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。
    那么就ok。得到的是一块连续的内存。
       如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
     并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。老块被放回堆上。
     如果是第二种情况的话,s->top 就不是原来的 top 了     --百度百科

      写这些代码的时候还是遇到了一些问题 在这里总结一下:

      第一 对于指针的使用要慎重 因为它传递进函数会改变原始数据,所以对于不需要改变

    指针指向的值的情况就不要使用指针。

      第二 对于指针的使用  如下定义 int *e=NULL; *e=3;

    看着好像没有问题  编译也没问题 但是运行程序就出错

    为什么?  没有为指针e分配内存地址 所以引用肯定错误啊(我这个逗逼错误-_-)

    正确的用法应该是 int *e=NULL;e=(int*)malloc(sizeof(int)); *e=3;

    我之前都是 int *e,a; e=&a; e=3; 这种用法 所以......

    
    
    
  • 相关阅读:
    XML学习笔记(七)Schema语法杂项
    UML和模式应用第一部分:绪论
    XML学习笔记(六)Schema语法之复杂类型
    XML学习笔记(四)Schema介绍篇
    XML学习笔记(三)进阶篇
    Xml学习笔记(二)Javascript篇
    AutoItLibrary安装报错(robotframework)解决
    robot framework 上个用例的输出作为下个用例的输入 (Set Global Variable的用法)
    robot framework ——关键字run keyword if 如何在一个条件下接多个执行语句,以及如何写复杂条件句
    robot framework 如何获取隐藏元素的文本,以及可见元素的文本
  • 原文地址:https://www.cnblogs.com/mwq1024/p/10146943.html
Copyright © 2011-2022 走看看