顺序栈的基本操作(C语言)
由于现在只学了C语言所以就写这个C语言版的栈的基本操作
这里说一下 :网上和书上都有这种写法 int InitStack(SqStack &p)
&p是取地址 但是这种用法好像C并不支持 ,C++才支持,所以用
C语言写就需要使用指针
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 100//储存空间初始分配量
#define STACKINCREMENT 10//存储空间分配增量
#define OK 1
#define ERROR 0
typedef int StackType; //栈元素类型 typedef struct {
StackType *base; //在构造之前和销毁之后,base的值为NULL
StackType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}SqStack; //顺序栈 //栈的初始化
int InitStack(SqStack *p) { p->base = (StackType*)malloc(STACK_INIT_SIZE * sizeof(StackType));
if (p->base == NULL) return ERROR; //内存分配失败
p->top = p->base; //栈顶与栈底相同表示一个空栈
p->stacksize = STACK_INIT_SIZE;
return OK; }
//判断栈是否为空
int EmptyStack(SqStack *p) {
//若为空栈 则返回OK,否则返回ERROR
if (p->top == p->base) return OK;
else return ERROR;
}
//顺序栈的压入
int Push(SqStack *p,StackType e) {
//插入元素e为新的栈顶元素
if ((p->top - p->base)>= p->stacksize) //栈满,追加储存空间
{
p->base = (StackType*)realloc(p->base, (p->stacksize + STACKINCREMENT) * sizeof(StackType));
if (p->base == NULL) return ERROR;// 储存空间分配失败
p->top = p->base + p->stacksize; //可能有人觉得这句有点多余(我当时也是这么想的 后面有解释)
p->stacksize += STACKINCREMENT;
}
*(p->top) = e;
(p->top)++;
return OK;
}
// 顺序栈的弹出
int Pop(SqStack *p,StackType *e) {
//若栈不空,则删除p的栈顶元素,用e返回其值
if (p->top == p->base) return ERROR;
--(p->top);
*e = *(p->top);
return OK; }
//顺序栈的销毁
int DestroyStack(SqStack *p) {
//释放栈底空间并置空
free(p->base);
p->base = NULL;
p->top = NULL;
p->stacksize = ; return OK;
}
//将顺序栈置空 栈还是存在的,栈中的元素也存在,如果有栈中元素的地址任然能调用
int ClearStack(SqStack *p) {
p->top= p->base;
return OK;
}
//返回顺序栈的元素个数
int StackLength(SqStack p) {
//栈顶指针减去栈底指针等于长度,因为栈顶指针指向当前栈顶元素的下一个位置
return p.top - p.base;
}
//返回顺序栈的栈顶元素
int GetTop(SqStack *p, StackType *e) {
//若栈不为空,则用e返回p的栈顶元素
if (p->top > p->base) {
*e = *(p->top - ); return OK;
}
else return ERROR;
}
//从栈顶到栈底对每个元素调用某个函数
int StackTraverse(SqStack p,void (*pfun)(StackType)/*函数指针*/){
//从栈底到栈顶依次对栈中的每个元素调用函数pfun()
while (p.top > p.base)
pfun(*(p.base)++); //先调用后递增
printf("\n");
return OK;
}
//打印栈中元素
void print(StackType stack) {
printf("%d\n", stack); }
//测试栈的各种操作
int main() {
int n,i;
StackType *e,a;
SqStack *pstack,stack;
pstack = &stack;
e=(StackType*)malloc(sizeof(StackType)); //为指针e分配内存地址
InitStack(pstack); //初始化栈 if (EmptyStack(pstack) == 1) printf("-------栈为空-------\n");
printf("请输入栈的元素个数:");
scanf("%d", &n);
for (i = ; i < n; i++)
{
scanf("%d", &a);
Push(pstack, a);
}
if (EmptyStack(pstack) == 0) printf("-------栈不为空-----\n"); printf("栈的长度为:%d\n", StackLength(stack));
printf("--------------------\n");
printf("请输入一个入栈元素:");
scanf("%d", &a);
Push(pstack, a);
printf("--------------------\n");
printf("栈中的元素个数为:%d\n", StackLength(stack));
printf("--------------------\n");
GetTop(pstack, e);
printf("栈顶元素为:%d\n", *e);
printf("--------------------\n");
printf("打印栈中的元素:\n");
StackTraverse(stack, print);
printf("---弹出栈顶元素---\n");
Pop(pstack, e);
printf("弹出的栈顶元素为:%d\n", *e);
printf("--------------------\n");
GetTop(pstack, e);
printf("栈顶元素为:%d\n", *e);
printf("--------------------\n");
printf("打印栈中的元素:\n");
StackTraverse(stack, print);
printf("--------------------\n"); printf("----------清空栈-------\n");
if (ClearStack(pstack) == ) printf("已清空栈\n"); printf("----------销毁栈-------\n");
if (DestroyStack(pstack) == ) printf("已销毁栈\n");
return ; }
第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; 这种用法 所以......
顺序栈的基本操作(C语言)的更多相关文章
- D_S 顺序栈的基本操作
// main.cpp #include <iostream> using namespace std; #include "Status.h" typedef in ...
- 链栈的基本操作(C语言)
栈的链式储存结构称为链栈.链栈的节点类型与链式线性表的节点类型 定义相同,不同的是它是仅在表头进行操作的单链表.链栈通常用不带头节 点的单链表来实现,栈顶指针就是链表的头指针 ,如图所示: 代码如下: ...
- php模拟顺序栈基本操作
php模拟顺序栈基本操作 一.总结 写函数什么永远记住边界情况:比如 echo "栈已满!<br/>" ; 栈已空这种,那就能多考虑几种情况,代码就很正宗了 1.对象 ...
- C++语言实现顺序栈
C++语言实现顺序栈 在写C语言实现顺序栈的时候,我已经向大家介绍了栈的特点以及介绍了栈的相关操作,并利用C语言实现了相关算法.在这里小编就不在继续给大家介绍了,需要温习的可以去我的博客看看.在这篇博 ...
- 把十进制整数转换为r(r=2)进制输出(顺序栈实现)
上周的第二个作业补上~~ 上周的要求: 1.给出顺序栈的存储结构定义. 2.完成顺序栈的基本操作函数. 1) 初始化顺序栈 2) 实现入栈和出栈操作 3) 实现取栈顶元素 ...
- 数据结构之顺序栈SqStack
顺序栈SqStack 基本操作 Status InitStack()//构造一个空栈S Status DestroyStack()//销毁栈S,S不再存在 Status ClearStack()//把 ...
- 数据结构——Java实现顺序栈
一.分析 栈是限定仅在表的一端进行插入或删除操作的线性表,对于栈来说,操作端称为栈顶,另一端则称为栈底,栈的修改是按照后进先出的原则进行的,因此又称为后进先出的线性表. 顺序栈是指利用顺序存储结构实现 ...
- 数据结构(C实现)------- 顺序栈
栈是限定仅在表的一端进行插入或删除的纯属表,通常称同意插入.删除的一端为栈顶(Top),对应在的.则称还有一端为栈底(Bottom). 不含元素的栈则称为空栈. 所设栈S={a1,a2,a3,..., ...
- C语言实现顺序栈以及栈的特点
什么是栈? 同顺序表和链表一样,栈也是用来存储逻辑关系为 "一对一" 数据的线性存储结构,如下图所示. 从上图我们看到,栈存储结构与之前所学的线性存储结构有所差异,这缘于栈对数据 ...
随机推荐
- 关于分布式uuid的一点设想
在一次公开课上,听别人讲过全局分布式uuid的设计,听过twitter的snowflake的设计.也听过,如果使用单独的计数器服务,不可能每次都保存当前计数器到文本,自己想到应该可以每隔一些数,例如1 ...
- [UE4]Named Slot
用户创建的UI成为其他UI的子控件的时候,默认情况下是不能拥有子控件的,给UI添加一个Named Slot,这个UI就可以拥有子控件 一.创建一个名为testNameSlot的UI,添加3个Named ...
- 使用Oracle DBLink进行数据库之间对象的访问操作
Oracle中自带了DBLink功能,它的作用是将多个oracle数据库逻辑上看成一个数据库,也就是说在一个数据库中可以操作另一个数据库中的对象,例如我们新建了一个数据database1,我们需要操作 ...
- 【Selenium】各种方式在选择的时候应该怎么选择
最后再总结一下,各种方式在选择的时候应该怎么选择: 1. 当页面元素有id属性时,最好尽量用id来定位.但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法. ...
- python中定时任务
今天看网络框架时,突然想看一下定时器,于是往上搜索了一下python中timer task的实现,但是由于python本身对线程的支持不是太好,因为全局排它锁的存在,使得多线程在访问资源时效率比较低. ...
- Oracle 事务和异常处理
Oracle 的异常和回滚 DECLARE dept_no ) :; BEGIN --开始事务 INSERT INTO dept VALUES (dept_no, '市场部', '北京'); --插入 ...
- [Ting's笔记Day4]将Ruby on Rails项目部署到Heroku
今天想笔记的是把自己写的Ruby on Rails项目部署(Deploy)到Heroku! Heroku是Salesforce公司旗下的云端服务商,支持多种程序语言像是Ruby,PHP,Python等 ...
- vue初体验
作为一个前端的小菜鸟,在平时的开发与学习中,除了要深入了解javascript 及 css 的各种特性,熟悉一门框架也是必不可少的.vue以其小巧,轻便,学习平滑等各种特性深受欢迎. 这里总结一下小菜 ...
- 在ASP.NET MVC中使用Area区域
在大型的ASP.NET mvc5项目中一般都有许多个功能模块,这些功能模块可以用Area(中文翻译为区域)把它们分离开来,比如:Admin,Customer,Bill.ASP.NET MVC项目中把各 ...
- iOS的SVN
1.cornerstone 2.smart svn mac (比较好用) 3.还xcode自带的.