顺序栈的栈基本操作(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 0
  6 #define ERROR 1
  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
 41         /*p->top = p->base + p->stacksize;这句是有必要加上的
 42         这一个问题的关键在于 realloc 是怎么实现的,有两种情况:
 43             如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address。
 44         这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时,
 45         realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。
 46         也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。
 47         那么就ok。得到的是一块连续的内存。
 48             如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
 49         并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。老块被放回堆上。
 50         如果是第二种情况的话,s->top 就不是原来的 top 了--百度百科*/
 51
 52         p->stacksize += STACKINCREMENT;
 53     }
 54     *(p->top) = e;
 55     (p->top)++;
 56     return OK;
 57 }
 58  // 顺序栈的弹出
 59 int Pop(SqStack *p,StackType *e) {
 60     //若栈不空,则删除p的栈顶元素,用e返回其值
 61     if (p->top == p->base) return ERROR;
 62     --(p->top);
 63     *e = *(p->top);
 64     return OK;
 65
 66
 67 }
 68 //顺序栈的销毁
 69 int DestroyStack(SqStack *p) {
 70     //释放栈底空间并置空
 71         free(p->base);
 72         p->base = NULL;
 73         p->top = NULL;
 74         p->stacksize = 0;
 75
 76         return OK;
 77 }
 78 //将顺序栈置空 栈还是存在的,栈中的元素也存在,如果有栈中元素的地址任然能调用
 79 int ClearStack(SqStack *p) {
 80     p->top= p->base;
 81     return OK;
 82 }
 83 //返回顺序栈的元素个数
 84 int StackLength(SqStack p) {
 85     //栈顶指针减去栈底指针等于长度,因为栈顶指针指向当前栈顶元素的下一个位置
 86     return p.top - p.base;
 87 }
 88 //返回顺序栈的栈顶元素
 89 int GetTop(SqStack *p, StackType *e) {
 90     //若栈不为空,则用e返回p的栈顶元素
 91     if (p->top > p->base) {
 92         *e = *(p->top - 1); return OK;
 93     }
 94     else return ERROR;
 95 }
 96 //从栈顶到栈底对每个元素调用某个函数
 97 int StackTraverse(SqStack p,void (*pfun)(StackType)/*函数指针*/){
 98 //从栈底到栈顶依次对栈中的每个元素调用函数pfun()
 99     while (p.top > p.base)
100     pfun(*(p.base)++);                //先调用后递增
101     printf("\n");
102     return OK;
103 }
104 //打印栈中元素
105 void print(StackType stack) {
106     printf("%d\n", stack);
107
108 }
109 //测试栈的各种操作
110 int main() {
111     int n,i;
112     StackType *e,a;
113     SqStack *pstack,stack;
114     pstack = &stack;
115     e=(StackType*)malloc(sizeof(StackType));    //为指针e分配内存地址
116     InitStack(pstack);                            //初始化栈
117
118     if (EmptyStack(pstack) == 0) printf("-------栈为空-------\n");
119     printf("请输入栈的元素个数:");
120     scanf("%d", &n);
121     for (i = 0; i < n; i++)
122     {
123         scanf("%d", &a);
124         Push(pstack, a);
125     }
126     if (EmptyStack(pstack) == 1) printf("-------栈不为空-----\n");
127
128     printf("栈的长度为:%d\n", StackLength(stack));
129     printf("--------------------\n");
130     printf("请输入一个入栈元素:");
131     scanf("%d", &a);
132     Push(pstack, a);
133     printf("--------------------\n");
134     printf("栈中的元素个数为:%d\n", StackLength(stack));
135     printf("--------------------\n");
136     GetTop(pstack, e);
137     printf("栈顶元素为:%d\n", *e);
138     printf("--------------------\n");
139     printf("打印栈中的元素:\n");
140     StackTraverse(stack, print);
141     printf("---弹出栈顶元素---\n");
142     Pop(pstack, e);
143     printf("弹出的栈顶元素为:%d\n", *e);
144     printf("--------------------\n");
145     GetTop(pstack, e);
146     printf("栈顶元素为:%d\n", *e);
147     printf("--------------------\n");
148     printf("打印栈中的元素:\n");
149     StackTraverse(stack, print);
150     printf("--------------------\n");
151
152     printf("----------清空栈-------\n");
153     if (ClearStack(pstack) == 0)  printf("已清空栈\n");
154
155     printf("----------销毁栈-------\n");
156     if (DestroyStack(pstack) == 0)  printf("已销毁栈\n");
157     return 0;
158
159 }

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

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

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

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

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

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

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

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



原文地址:https://www.cnblogs.com/mwq1024/p/10146943.html

时间: 2024-10-25 17:00:36

顺序栈的栈基本操作(C语言版)的相关文章

数据结构(C语言版)顺序栈相关算法的代码实现

这两天完成了栈的顺序存储结构的相关算法,包括初始化.压栈.出栈.取栈顶元素.判断栈是否为空.返回栈长度.栈的遍历.清栈.销毁栈.这次的实现过程有两点收获,总结如下: 一.清楚遍历栈的概念 栈的遍历指的是从栈底想栈顶方向运行visit()函数,这是之前的学习中所忽略的:栈的遍历解除了栈的输出顺序只能从栈顶像栈底方向的限制. 二.清空栈时要不要将stacksize重置 网上看到有的人在实现清空栈这一功能时,将stacksize重置为0,我觉得有点问题,起初的想法是将其重置为初始化时的值,在与同学讨论

深入浅出数据结构C语言版(8)——后缀表达式、栈与四则运算计算器

在深入浅出数据结构(7)的末尾,我们提到了栈可以用于实现计算器,并且我们给出了存储表达式的数据结构(结构体及该结构体组成的数组),如下: //SIZE用于多个场合,如栈的大小.表达式数组的大小 #define SIZE 1000 //表达式的单个元素所使用的结构体 typedef struct elem { int num = 0; //若元素存储操作数则num为该操作数 char oper = '='; //若元素存储操作符则oper为该操作符 bool IsNum = false; //用于

数据结构 - 顺序栈的实行(C语言)

数据结构-顺序栈的实现 1 顺序栈的定义 既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化,我们简称为顺序栈.线性表是用数组来实现的,对于栈这种只能一头插入删除的线性表来说,用数组哪一端来作为栈顶和栈底比较好? 对,没错,下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作栈底. 我们定义一个top变量来指示栈顶元素在数组中的位置,这top就如同中学物理学过的游标卡尺的游标,它可以来回移动,意味着栈顶的top可以变大变小,但无论如何游标不能超出尺的长度.同理

数据结构之栈定义及基本操作实现

终于有可以有时间写点数据结构的学习总结了,前段时间一直在紧张的忙一些项目,都没有空出时间来学习数据结构,现在终于可以稍微喘口气了,还是数据结构有意思,这两天看了点栈的东西,写下来总结一下,有错误的地方希望看到的朋友指出来,感激不尽. 根据学习,栈就是一种线性数据结构,栈的运算只能在表的一段进行,所以这种数据结构具有“后进先出”的特点. 接下来是栈的c语言实现.其中栈由一个top节点和bottom节点组成,这两个节点分别指向栈的顶部和底部.其中栈的组成结点是由结构体实现,结构体由数据库和指向下一个

顺序栈——双栈(Dual Stack)

顺序栈--双栈(Dual Stack) 1. 双栈的概念 1.1 双栈的定义 双栈是指两个顺序栈,是一种特殊的顺序栈. 1.2 双栈中各元素的逻辑及存储关系 双栈共享一个地址连续的存储单元.即程序同时需要两个栈时,可以定义一个足够的栈空间,该空间的两端分别设为两个栈的栈底,用bottom[0]=-1和bottom[1]=maxSize指示. 压入数据时,让两个栈的栈顶top[0]和top[1]都向中间伸展,如果指示栈顶的指针top[0]+1等于另一个栈顶的指针top[1]时两栈已满. 每次进栈时

顺序栈的初始化入栈出栈以及打印栈的信息

使用的开发工具CLion CLion 2017.2.1 Build #CL-172.3544.40, built on August 2, 2017Licensed to CLion EvaluatorExpiration date: September 15, 2017JRE: 1.8.0_152-release-915-b6 x86_64JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.oMac OS X 10.12.4   1 #include

Java语言描述顺序表类,顺序表类的基本操作实现

数据结构(Java版)ch2 线性表的顺序存储(顺序表) 线性表的抽象数据Java接口描述如下: package ch2; /** * 线性表的抽象数据接口,用Java语言描述线性表的这些功能! * @author 房廷飞 * */ public interface IList { public void clear(); //将线型表置成空表 public boolean isEmpty(); //判断是不是空表 public int length(); //返回线性表的长度 public O

栈实现迷宫求解(c++版)

相信大家都应该听过栈吧,一直想利用栈来实现一个算法,最近有点空,就利用栈的先进后出的特性来完成迷宫求的问题,下面将详细介绍栈的实现和迷宫求解的过程,可以很好的学习栈的使用. 栈有两种实现方法,一种是顺序,即数组形式,一种是线性,即链表形式,个人还是比较喜欢链表形式实现栈的基本功能. 首先弄一个简单的迷宫,如图: 我们很容易看出这个迷宫解的路径,那怎么让计算机帮我们求解出来呢. 首先我们要对迷宫数据化,很容易想到二维数组来表示,0表示通路,1表示障碍,即表示为: int map[4][4]={ {

模板(顺序表与栈)

"顺序表与栈" 顺序表相对于我们来说已经不算是陌生的,顺序表有自己独有的特点,需要有一块独有的空间,访问中间的数据也较为简单,插入和删除数据就相对较难.针对顺序表的特点,我们不难想到一个数据结构"栈",栈的特点与顺序表相对来说很接近,栈的主要特点是"先进后出",即就是后进入栈的数据必须先出才能够访问到先前进入的数据,用顺序表来实现"栈"的一些基本功能更加合适. 这里首先提一下"模板"的概念,模板的一般形式为