数据结构之栈

目录

一、栈的基本概念

二、顺序栈

        1、顺序栈的定义

        2、顺序栈的基本操作

        3、共享栈

三、链栈

四、栈的应用

        1、栈在括号匹配中的应用

        2、栈在表达式求值中的应用 

        3、栈在递归中的应用  


一、栈的基本概念

        栈是只允许在一端进行插入或删除操作的线性表。

        栈顶:线性表允许进入插入删除的那一端。

        栈底:固定的,不允许进入插入和删除的另一端。

        空栈:不含任何元素的空表。

        假设某个栈如图所示,a1为栈底元素,a5为栈顶元素。栈只能在栈顶进行插入和删除操作,进栈次序依次为a1,a2,a3,a4,a5,而出栈次序为a5,a4,a3,a2,a1。由此可见,栈的操作特性可以明显地概括为后进先出。 

每接触一种数据结构,都应从其逻辑结构、存储结构和运算三个方面着手

二、顺序栈

        1、顺序栈的定义

        采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(top)指示当前栈顶元素的位置。栈的顺序存储类型可描述为

#define MaxSize 50            //定义栈中元素的最大个数
typedef struct{
	Elemtype data[MaxSize];    //存放栈中元素
	int top;                    //栈顶指针
}SqStack;

        2、顺序栈的基本操作

        (1)初始化

        初始时设置S.top=-1;栈顶元素:S.data[S.top]。

void InitStack(SqStack &S){
	S.top=-1;		//初始化栈顶指针
}

        (2)判栈空

bool StackEmpty(SqStack S){
	if(S.top==-1)
		return true;		//栈空
	else
		return false;		//不空
}

        (3)进栈 

        栈不满时,栈顶指针先加1,再送值到栈顶。

        (4)出栈 

        栈非空时,先取栈顶元素,再将栈顶指针减1。

bool Pop(SqStack &S,ElemType &x){
	if(S.top==-1)		//栈空,报错
		return false;
	x=S.data[S.top--];	//先出栈,指针再减1
	return true;
}	

        (5)读栈顶元素

        仅为读取栈顶元素,并没有出栈操作,因此原栈顶元素依然保留在栈中。

bool GetTop(SqStack S,ElemType &x){
	if(S.top==-1)		//栈空,报错
		return false;
	x=S.data[S.top];	//x记录栈顶元素
	return true;
}

 这里的top指的是栈顶元素。于是,进栈操作为S.data[++S.top]=x,出栈操作为x=S.data[S.top--]。若栈顶指针初始化为S.top=0,即top指向栈顶元素的下一位置,则入栈操作变为S.data[S.top++]=x;出栈操作变为x=S.data[--S.top]。相应的栈空和栈满条件也会发生变化。

         顺序栈的入栈操作受数组上界的约束,当对栈的最大使用空间估计不足时,有可能发生栈上溢,而分配较大的空间容易造成浪费。

        3、共享栈

        利用栈底位置相对不变的特性,可让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。

        两个栈的栈顶指针都指向栈顶元素,top0=-1时0号栈为空,top1=MaxSize时1号栈为空;仅当两个栈顶指针相邻时(top1-top0=1)时,判断为栈满。当0号栈进栈时,top0先加1再赋值,1号栈进栈时,top1先减1再赋值;出栈时则刚好相反。 

        共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才发生上溢。其存储数据的时间复杂度均为O(1),所以对存取效率没有什么影响。

三、链栈

        采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,链头作为栈顶,并规定所有的操作都是在单链表的表头进行的。这里规定链栈没有头结点,Lhead指向栈顶元素,如图所示。

        栈的链式存储类型可描述为

typedef struct Linknode{
	ElemType data;				//数据域
	struct Linknode *next;		//指针域
}LiStack;						//栈类型定义

        采用链式存储,便于结点的插入和删除。链栈的操作与链表类似,入栈和出栈的操作都在链表的表头进行。需要注意的是,对于带头结点和不带头结点(推荐)的链栈,具体实现会有所不同。

设输入序列为1,2,3,则经过栈的作用后可以得到()中不同的输出序列。合法出栈数目==卡特兰数,公式为:f(n)=\frac{\textrm{C}_{2n}^{n}}{n+1} 

四、栈的应用

        1、栈在括号匹配中的应用

        2、栈在表达式求值中的应用 

        中缀转后缀表达式,使用左优先原则:只要左边的运算符能先计算,就优先算左边的。

        中缀转前缀表达式,使用右优先原则:只要右边的运算符能先计算,就优先算右边的。

        后缀表达式的手算方法:从左往右扫描,每遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合体为一个操作数。

        3、栈在递归中的应用  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值