栈的基本概念和基本操作的实现

本文介绍了栈的基本概念,包括栈顶、栈底和后进先出的特点。详细阐述了顺序栈的定义、初始化、判断空栈、入栈、出栈和读取栈顶元素的操作。此外,讨论了顺序栈的缺点并提出了共享栈的概念,指出共享栈在空间利用上的优势。最后,简要提及了链栈作为另一种实现方式,同样包含了初始化、入栈、出栈和获取栈顶元素等操作。

1.定义:栈(stack)是只允许在一端进行插入或删除操作的线性表

重要术语:栈顶、栈底、空栈

栈顶:允许插入和删除的一端                         栈底:不允许插入和删除的一端

栈的特点:后进先出(LIFO ~ last in first out)

n个不同的元素进栈,出栈元素不同排列的个数有 种

 

2.顺序栈

(1)顺序栈的定义:

#define MAXSIZE 10           //定义栈中元素个数
typedef struct {
	int a;            
	double b;
}*ElemType;                 //栈中元素的类型

typedef struct SqStack {
	ElemType data[MAXSIZE];      //用静态数组存放栈中元素
	int top;     //栈顶指针
}SqStack;

(2)栈的初始化:

两种思想:

a.栈顶指针用于指向栈顶元素的位置,所以在没有元素时,让top指针指向0位置是不合理的。

因此,规定在栈中没有元素时,栈顶指针指向-1。

b.栈顶指针指向栈顶元素的下一个位置,因此在没有元素时,让top指针指向0位置

本文采用思想a,至于思想b,请各位读者自行实现。

代码实现如下:

void InitStack(SqStack &S) {
	S.top = -1;
}

(3)判断是否为空栈:

由(2)可知,当栈为空时,栈顶指针指向-1位置,若空栈返回true,非空栈返回false,则实现如下:

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

(4)入栈(增):

入栈需要考虑栈的内存是否已满,若已满则返回false。

bool Push(SqStack& S, ElemType e) {
	if (S.top + 1 == MAXSIZE)        //栈满
		return false; 
	S.top += 1;             //让栈顶指针向后移动一位
	S.data[S.top] = e;
	return true;
}

//上述操作也可简化为如下代码
bool Push(SqStack& S, ElemType e) {
	if (S.top + 1 == MAXSIZE)
		return false;
	S.data[++S.top]=e;       //注意:由于需要先++后运算,所以不能写成S.top++
	return true;
}

(5)栈顶元素出栈(删):

出栈操作需要删除栈顶元素,并用e将其带回,同时使栈顶指针减1

出栈操作需要考虑到栈是否为空,若为空栈,则无法实现栈顶元素出栈操作,故返回false

bool Pop(SqStack& S, ElemType& e) {   //因为要用元素e将栈顶元素带回,因此需要用到引用&
	if (-1 == S.top)        //空栈
		return false;
	e = S.data[S.top];      
    S.top--;              //栈顶指针下移
	return true;
}

//同入栈函数,出栈函数也可简化为:
bool Pop(SqStack& S, ElemType& e) {
	if (-1 == S.top)        //空栈
		return false;
	e=S.data[S.top--];
	return true;
}

(6)读取栈顶元素(查):

该函数与出栈函数几乎相同,唯一的不同是栈顶指针不用下移

bool GetTop(SqStack S,ElemType& e) {
	if (-1 == S.top)   //空栈
		return false;
	e = S.data[S.top];
	return true;
}

(7)顺序栈的缺点:栈的大小不可变,可能会导致大片空间的浪费,可以采用共享栈来减少空间的浪费。

3.共享栈:两个栈共享一片存储空间

判断共享栈满的条件:top0+1==top1

这里只简单列举一些操作,有关共享栈的其他操作大家可以自行实现。

(1)共享栈的定义:

typedef struct {
	ElemType data[MAXSIZE];
	int top0, top1;    //0号栈顶指针和1号栈顶指针
}ShStack;

(2)初始化共享栈:

void InitStack(ShStack& S) {    //两个栈分别从栈底和栈顶出发
	S.top0 = -1;        
	S.top1 = MAXSIZE;
}

(3)判断是否为空栈:

bool Empty(ShStack S) {
	if (S.top0 == -1 && S.top1 == MAXSIZE)
		return true;
	return false;
}

4.链栈:用链式存储的方式实现的栈

(1)链栈的定义:

与链表的定义相同

typedef struct LinkNode{
	ElemType data;
	struct LinkNode* next;
}*LiStack;

(2)链栈的初始化:

//对于链栈,我们常采用不带头结点的链表来实现
void InitStack(LiStack& S) {
	S = NULL;
}

(3)链栈的判空:

bool Empty(LiStack S) {
	if (S == NULL)     //空栈
		return true;
	return false;
}

 (4)入栈:

链栈插入元素的方式其实就是链表对头结点的后插操作。

bool Push(LiStack& S,ElemType e) {  //链栈不会有栈满的情况,因此不需要判断
	LinkNode* p = new LinkNode;
	if (p == NULL)
		return false;
	p->data = S->data;        //将头指针中存放的值赋给新的指针p
	S->data = e;              //将头指针中的值改为e
	p->next = S->next;        //让p指向头指针的下一个结点
	S->next = p;              //让头指针的下一个结点为p 
	return true;
}

 (5)出栈:

bool Pop(LiStack &S, ElemType& x) {
	if (S == NULL)              //空栈
		return false;
	x = S->data;             //将栈顶元素赋给x
	LinkNode* p = new LinkNode;
	p = S;                //让p指针指向S
	S = S->next;
	delete p;             //删除栈顶元素
	return true;
}

(6)获取栈顶元素:

bool GetTop(LiStack S, ElemType& x) {
	if (S == NULL)        //空栈
		return false;
	x = S->data;
	return true;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值