【数据结构之栈】

栈的定义

栈是限定仅在表尾进行插入删除操作的线性表。因此,表尾对栈有特殊的意义,称为栈顶,相应地,表头称为栈底,不含元素的空表叫空栈。
在这里插入图片描述

顺序栈的表示和实现

栈的定义

由于我们在栈中只对栈顶插入和删除,所以我们需要一个栈顶指针,当满栈的时候,我们需要对栈进行扩容,所以也需要一个参数来表示当前栈的大小,当我们在进行删除操作的时候,要判断栈是否下溢,这就需要一个栈底指针,这就是定义顺序栈的基本元素。

#define STACKsize 100//存储空间初始分配量
#define STACKIN  10//存储空间分配增量
#define OK 1
#define over -2
typedef int SDatatype;
typedef int status; 

typedef struct{
	SDatatype *base;//栈底指针,在栈构造之前和销毁之后,base为NULL
	SDatatype *top;//栈顶指针
	int stacksize;//当前已分配的空间,以元素为单位
}sqstack;

栈的初始化

每次创建一个新栈的时候,栈顶指针总是和栈底指针相等的。

//初始化顺序栈
 
status Inistack(sqstack &s){
	s.base = (SDatatype *)malloc(STACKsize*sizeof(SDatatype));//申请内存空间
	if(!s.base){
		return over;//初始化失败
	}
	s.top = s.base;
	s.stacksize = STACKsize;
	return OK;
}

入栈

只要是入栈的时候,都要判断栈是否满了,满了就得扩容

//入栈
status push(sqstack &s,SDatatype e){
	SDatatype *p;
	//判断是否满栈
	if(s.top-s.base == s.stacksize){
		p = (SDatatype *)realloc(s.base,(STACKsize+STACKIN)*sizeof(SDatatype));
		if(!p){
			return over;
		}
		s.base = p;//系统会将原来的栈复制过来 
		s.top = s.base+s.stacksize;//使top指向新的栈顶 
		s.stacksize += STACKIN;
	} 
	*(s.top)++ = e;//入栈 
	return OK;
} 

出栈

每次出栈,都得判断栈是否为空了

//出栈
status pop(sqstack &s,SDatatype &e){
	//判断是否发生下溢
	if(s.top != s.base){
		e = *--s.top; //先将栈顶减1 
	} 
	else return 0;
	return e;
} 

判断是否为空栈

//判断是否为空栈
bool stacknull(sqstack &s){
	if(s.top == s.base){
		return true; 
	}
	else return false; 
} 

取栈顶元素

//取栈顶元素
SElemType GetTop(SqStack S)
{
	if (S.top != S.base)	 //非栈空时返回
		return *(S.top - 1);   //++会改变指针自身值,而-1不会改变
}

栈的遍历

//遍历输出栈
void printStack(SqStack S)
{
	printf("base:");
	SElemType* p = S.base;
	while (p != S.top)
	{
		printf("%d ", *p);
		p++;
	}
	printf("\n");
}

栈的销毁

//栈的销毁
SElemType DestroyStack(SqStack& s)
{
	free(s.base);
	s.base = NULL;
	s.top = NULL;
	s.stacksize = 0;
	return 1;
}

完整代码

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 100
typedef int SElemType;

//顺序栈的存储结构
typedef struct
{
	SElemType* base;
	SElemType* top;
	int stacksize;			//可用最大容量
}SqStack;

//初始化
void InitStack(SqStack& S)
{
	S.base = new SElemType[MAXSIZE];
	if (!S.base) exit;
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

//入栈
int Push(SqStack& S, SElemType e)
{
	if (S.top - S.base == S.stacksize) return 0;	//栈满

	*S.top = e;
	S.top++;
	return 1;
}

//出栈
int Pop(SqStack& S, SElemType& e)
{
	if (S.top == S.base) return 0;    //栈空

	S.top--;
	e = *S.top;
	return 1;
}

//取栈顶元素
SElemType GetTop(SqStack S)
{
	if (S.top != S.base)	 //非栈空时返回
		return *(S.top - 1);   //++会改变指针自身值,而-1不会改变
}

//遍历输出栈
void printStack(SqStack S)
{
	printf("base:");
	SElemType* p = S.base;
	while (p != S.top)
	{
		printf("%d ", *p);
		p++;
	}
	printf("\n");
}

int main()
{
	SqStack S;
	int e;
	InitStack(S);
	printf("Please input a number to push(-1 end):");
	scanf("%d", &e);
	while (e != -1)
	{
		Push(S, e);
		printf("Please input a number to push(-1 end):");
		scanf("%d", &e);
	}
	printStack(S);
	printf("pop test:");
	Pop(S, e);
	printStack(S);

	printf("GetTop test:");
	e = GetTop(S);
	printf("The top number is:%d\n", e);
}

运行结果:
在这里插入图片描述

栈的应用

进制转换

核心思想:
每次将N对a的余数进栈,再将N/a,最后依次出栈

#include<stdio.h>
#include<malloc.h>


#define STACKsize 100
#define STACKIN  10
#define OK 1
#define over -2
typedef int SDatatype;
typedef int status; 

typedef struct{
	SDatatype *base;
	SDatatype *top;
	int stacksize;
}sqstack;


//初始化顺序栈
 
status Inistack(sqstack &s){
	s.base = (SDatatype *)malloc(STACKsize*sizeof(SDatatype));
	if(!s.base){
		return over;
	}
	s.top = s.base;
	s.stacksize = STACKsize;
	return OK;
}

//入栈
status push(sqstack &s,SDatatype e){
	SDatatype *p;
	//判断是否满栈
	if(s.top-s.base == s.stacksize){
		p = (SDatatype *)realloc(s.base,(STACKsize+STACKIN)*sizeof(SDatatype));
		if(!p){
			return over;
		}
		s.base = p;//系统会将原来的栈复制过来 
		s.top = s.base+s.stacksize;//使top指向新的栈顶 
		s.stacksize += STACKIN;
	} 
	*(s.top)++ = e;//入栈 
	return OK;
} 

//出栈
status pop(sqstack &s,SDatatype &e){
	//判断是否发生下溢
	if(s.top != s.base){
		e = *--s.top; //先将栈顶减1 
	} 
	else return 0;
	return e;
} 

//判断是否为空栈
bool stacknull(sqstack &s){
	if(s.top == s.base){
		return true; 
	}
	else return false; 
} 


void conversion(){
	sqstack s;
	int e,N;
	Inistack(s);
	printf("请输入一个十进制数:\n");
	scanf("%d",&N);
	printf("请输入想转换的进制:\n");
	int a;
	scanf("%d",&a);
	while(N){
		push(s,N%a);
		N /= a;
	}
	printf("转换后是:\n");
	while(!stacknull(s)){
		pop(s,e);
		printf("%d",e);
	}
} 

main(){
	conversion();
}

括号匹配

核心思想:
遇到做左括号就进栈,遇到右括号就判断栈顶的左括号是否匹配,匹配就出栈,最后如果括号是匹配的,栈就一定是空的,只要判断栈是否为空,就可以真的括号是否匹配了。

#include <stdlib.h>
#include "stdio.h"
#include "malloc.h"
#define OK 1
#define OVERFLOW -1
#define ERROR 0
#define STACK_INI_SIZE 100
#define STACKINCREMENT  10
typedef char ElemType;
typedef int Status;

typedef  struct{
     ElemType  *base;
     ElemType  * top;
     int   stacksize;
}SqStack;
Status InitStack(SqStack *S){
     // 构造一个空顺序栈 S
     S->base = (ElemType *)malloc(STACK_INI_SIZE* sizeof (ElemType));
     if (!S->base) exit (OVERFLOW); //存储分配失败
     S->top = S->base;
     S->stacksize = STACK_INI_SIZE ;
     return OK;

}
 
Status StackEmpty(SqStack S){
	 if(S.top==S.base) return OK;
	 else return ERROR;
}
Status Push(SqStack *S,ElemType e){
     if ((*S).top - (*S).base >= (*S).stacksize){   //栈满,追加存储空间
     (*S).base = (ElemType *)realloc((*S).base ,
     (STACK_INI_SIZE+STACKINCREMENT)* sizeof (ElemType));
     if(!S->base)   exit(OVERFLOW);     //存储分配失败
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;}
     *S->top++ = e;
     return OK;

}

Status Pop(SqStack *S,ElemType *e){
   // 若栈不空,则删除S的栈顶元素,
  // 用 e 返回其值,并返回OK;否则返回ERROR
     if (S->top == S->base) return ERROR;//栈空
     *e = *--S->top;
     return OK;

}
Status GetTop(SqStack S,ElemType *e){
//若栈顶不空,则用e返回S的栈顶元素,并返回ok;
//否则,返回ERROR
     if(S.top==S.base)  return ERROR;
     *e= *(S.top-1);
     return OK;
}
int DisplayStack(SqStack S){
     if(S.base==NULL){
         printf("栈已销毁!\n");
} 
     int len=S.top-S.base;
     if(len<=0){
	     printf("栈为空!\n");
}
     int k;
     for(k=0;k<=len;k++)
     printf("%c - ",S.base[k]);
     printf("%c\n",S.base[k]);
     return OK;
}

Status Brackets_Test(char *str){//判别表达式中三种括号是否匹配
     SqStack s;
     char c,*p;
     InitStack(&s); 
     for(p=str; *p; p++){
         if(*p=='('||*p=='['||*p=='{')    Push(&s,*p); 
         else if(*p==')'||*p==']'||*p=='}') { 
             if(StackEmpty(s)) { printf("it is error!\n");return ERROR; }
             Pop(&s,&c); 
             if(*p==')'&&c!='(') {printf("it is error!\n"); return ERROR;} 
             if(*p==']'&&c!='[') {printf("it is error!\n"); return ERROR; }
             if(*p=='}'&&c!='{') {printf("it is error!\n"); return ERROR; }//必须与当前栈顶括号匹配 
    } 
  }
     if(!StackEmpty(s))  {printf("it is error!\n");return ERROR; }
     printf("it is ok!\n");
     return OK; 
}

main (){
     char  ch[50];
     printf("栈已销毁!\n");
     gets(ch);
     Brackets_Test(ch);
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贩梦先生007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值