栈的存储结构、算法与应用

栈的存储结构、算法与应用

一、相关结构体定义

1.顺序栈定义

typedef struct{
	int data[maxSize];
	int top;
}SqStack;

2.链栈结点定义

typedef struct LNode{
	int data;
	struct LNode *next; 
}LNode;

二、顺序栈

1.顺序栈的要素
对于顺序栈st, 一共有4个要素,包括两个特殊状态和两个操作。
(1)几个状态
1)栈空状态。
st.top==-1
2)栈满状态。
st.top=maxSize-1. maxSize 为栈中最大元素的个数,则maxSize- 1为栈满时栈顶元素在数组中的位置,因为数组下标从0号开始。
3)非法状态(上溢和下溢)。
栈满就是一种继续入栈就会上溢的状态,对应的栈下溢就是栈空的时候继续出栈所造成的结果。
(2)两个操作
1)元素x进栈操作: ++(st.top);st.data[st.top]=x;。 既然规定了top为-1时栈为空,则元素进栈操作
必须是先移动指针,再进入元素,因为数组下标不存在-1。
2)元素x出栈操作: x=st.data[st.top];–(st.top);。 进栈操作次序决定了出栈操作次序,由于进栈操作是先变动栈顶指针,再存入元素,因此出栈操作必须为先取出元素,再变动指针。如果在上述进栈操作不变的情况下先变动指针,再取出元素,则栈顶元素丢失,取出的是栈顶下边的元素。
2.初始化栈的代码

//只需将栈顶指针置为-1即可 
void initStack(SqStack &st){
	st.top=-1;
}

3.判断栈空代码

//栈st为空的时候返回1,否则返回0 
int isEmpty(SqStack st){
	if(st.top==-1)
	return 1;
	else return 0;
}

4.进栈代码

int push(SqStack &st,int x){
	if(st.top==maxSize-1) return 0;
	++(st.top);
	st.data[st.top]=x;
	return 1;
}

5.出栈代码

int pop(SqStack &st,int &x){
	if(st.top==-1)
	return 0;
	x=st.data[st.top];
	--(st.top);
	return 1;
}

ps:大多时候为了方便采用如下写法
(1)定义一个栈并初始化

int stack[maxSize];int top=-1;

(2)元素x进栈

stack[++top]=x;

(3)元素x出栈

x=stack[top--];

三、链栈

1.链栈的要素
和顺序栈对应,链栈也有4个要素,包括两个特殊状态和两个操作。
(1)两个状态
1)栈空状态。

lst->next==NULL

2).栈满状态。
不存在栈满的情况(假设内存无限大的情况下不存在。一般题目要求不太严格, 可以这么认为)。
02)两个操作
1)元素(由指针p所指)进栈操作。

p->next=lst->next; lst->next=p;//其实就是头插法建立链表中的插入操作

2)出栈操作(出栈元素保存在x中)。

p=lst->next;x=p->data;lst->next=p->next;free (p);//其实就是单链表的删除操作

2.链栈的初始化代码

void initStack(LNode *&lst){
	lst=(LNode *)malloc(sizeof(LNode));
	lst->next=NULL;
}

3.判断栈空代码

void push(LNode *lst,int x){
	LNode *p;
	p=(LNode *)malloc(sizeof(LNode));
	p->next=NULL;
	p->data=x;
	p->next=lst->next;
	lst->next=p;
}

4.出栈代码

int pop(LNode *lst,int &x){
	LNode *p;
	if(lst->next==NULL) return 0;
	p=lst->next;
	x=p->data;
	lst->next=p->next;
	free(p);
	return 1;
}

四、栈的应用

1.顺序栈的应用

例1.编写算法,判断一个表达式中的括号是否正确配对,表达式已经存入字符数组exp[ ]中,表达式中的字符个数为n

代码如下:

int match(char exp[],int n){
	char stack[maxSize];int top=-1;
	int i;
	for(i=0;i<n;++i){
		if(exp[i]=='(')
		stack[++top]='(';
		if(exp[i]==')'){
			if(top==-1) return 0;
			else --top;
		}
	}
	if(top==-1) return 1;
	else return 0;
}

例2.编写一个函数,求后缀式的数值,期中后缀式存于一个字符数组exp中,exp中最后一个字符为‘\0’,作为结束符,并且假设后缀式中的数字都只有以为。本题中出现的除法运算皆为整除运算。
**执行过程:**当遇到数值的时候入栈,当遇到运算符的时候,连续两次出栈,将两个出栈元素结合运算符进行运算,将结果当成新遇到的数值入栈。如此往复,直到扫描到终止符“\0"。此时栈底元素即为表达式的值。

int op(int a,char Op,int b){  //运算函数 
	if(Op=='+') return a+b;
	if(Op=='-')return a-b;
	if(Op=='*')return a*b;
	if(Op=='/'){
		if(b==0){
			cout<<"ERROR"<<endl;
			return 0;
		}
		else return a/b;
	}
}
int com(char exp[]){
	int i,a,b,c;
	int stack[maxSize];int top=-1;
	char Op;
	for(i=0;exp[i]!='\0';++i){
		if(exp>='0'&&exp[i]<='9')
		stack[++top]=exp[i]-'0';//字符型和整型的转换
		else{
			Op=exp[i];
			b=stack[top--];
			a=stack[top--];
			c=op(a,Op,b);
			stack[++top]=c;
		} 
	}
	return stack[top];
} 

2.链栈的应用
例3:用不带头结点的单链表存储链栈,设计初始化栈,判断栈是否为空、进栈和出栈等相应的算法
分析:不带头结点的单链表lst为空的条件是lst==NULL,进栈和出栈操作都是在表头进行,算法入下:

void insertStackl(LNode *&lst){
	lst=NULL;
}
int isEmptyl(LNode *lst){
	if(lst==NULL)return 1;
	else return 0;
}
void pushl(LNode *&lst,int x){
	LNode *p;
	p=(LNode *)malloc(sizeof(LNode));
	p->next=NULL;
	p->data=x;
	p->next=lst;
	lst=p;
}
int popl(LNode *&lst,int &x){
	LNode *p;
	if(lst==NULL)
	return 0;
	p=lst;
	x=p->data;
	lst=p->next;
	free(p);
	return 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值