数据结构之顺序栈

栈的定义

栈是一个抽象的线性表,因此栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表。在线性表的表尾进行插入和删除操作,这里的表尾指的是栈顶,而不是栈底。这样使得它始终只在栈顶进行插入删除,栈底固定,最先进栈的只能在栈底。

栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈也称为后进先出(List In First Out)的线性表,简称LIFO结构。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针
 

栈的插入操作叫做进栈也称压栈、入栈。

栈的删除操作叫做出栈

也称弹栈。

注意:

  • 栈是一种特殊的线性表
  • 栈仅能在线性表的一端(栈顶)进行操作
  • 栈顶(Top):允许操作的一端
  • 栈底(Bottom):不允许操作的一端
  • 栈可以用来在函数调用的时候存储断点,做递归时要用到栈!

笔试习题:
  一个栈的入栈序列为ABCDEF,则不可能的出栈序列是(D) 
  A、DEFCBA    B、DCEFBA    C、FEDCBA 
  D、FECDBA    E、ABCDEF    F、ADCBFE

分析: 

该题主要是考虑栈的核心思想是先进后出,并且需要注意入栈和出栈的顺序是未知的,例如你可以先入栈ABCD,然后出栈D,然后入栈E,出栈E,入栈F,出栈F,然后CBA依次出栈,也就是A选项的情况。 
任何出栈的元素 后面出栈的元素必须满足以下三点: 

在原序列中相对位置比它小的,必须是逆序; 
在原序列中相对位置比它大的,顺序没有要求; 
以上两点可以间插进行。
  选项D的出栈顺序FECDBA,明显出栈元素F后面的元素C和D不满足上面规律1,所以选项D是错误的,其它答案都是满足的。

因为栈是由线性表实现的,所以,栈有两种存储结构:顺序存储和链式存储。即顺序栈和链式栈。


顺序栈

1.结构定义

#define STACK_LEN 20  // 初始化栈的大小为20
 
// 顺序栈的结构定义
typedef struct Sqstack
{
	int elem[STACK_LEN];   //  用于存放栈中元素的一维数组
	int top;   // 用来存放栈顶元素的下标

}Sqstack,*Pstack;

2.具体操作函数

值得注意的是,在这里因为是顺序结构你需要在
插入和出栈的时候,判断空或者满。


void InitStack(Pstack ps);
bool Push(Pstack ps,int val);
bool Pop(Pstack ps,int *rtv);//删除
bool GetTop(Pstack ps,int *rtv);//得到栈顶元素,但是不删除
bool IsEmpty(Pstack ps);
void Clear(Pstack ps);//top 指针的操作

 

void InitStack(Pstack ps)
{
	assert(ps != NULL);
	ps->top = 0;
}
static bool isFull(Pstack ps)
{
	return ps->top == STACK_LEN;
}
bool Push(Pstack ps, int val)
{
	if (isFull(ps))
	{
		return false;
	}
	ps->elem[ps->top++] = val;
	return true;
}
bool IsEmpty(Pstack ps)
{
	return ps->top == 0;
}

bool Pop(Pstack ps, int *rtv)//删除
{
	if (IsEmpty(ps))
	{
		return false;
	}
	if (rtv != NULL)
	{
		ps->top--;
		*rtv = ps->elem[ps->top];
	}
	return true;
}

bool GetTop(Pstack ps, int *rtv)//得到栈顶元素, 但是不删除
{
	if (IsEmpty(ps))
	{
		return false;
	}
	if (rtv != NULL)
	{
		*rtv = ps->elem[ps->top - 1];
	}
	return true;
}


void Clear(Pstack ps)//top 指针的操作
{
	ps->top = 0;
}

void Destroy(Pstack ps)
{
	Clear(ps);
}
void Show(Pstack ps)
{
	for (int i = 0; i < ps->top; i++)
	{
		printf("%d ", ps->elem[i]);
	}
	printf("\n");
}

顺序栈的扩容


之前顺序栈中数组的长度为define宏定义的常数。当元素个数超过数组最大长度时,就会插入失败。同顺序表的扩容一样,也可以实现扩容的顺序栈。即当元素个数超过设定的最大长度时,可以在再动态申请更大的内存来存放元素。

首先,因为该顺序栈要实现扩容,则不能用数组来实现。因此可以动态申请一块内存,将栈中元素放入其中。通过动态内存申请返回的指针来以数组的形式访问栈中元素。

其次,该动态内存的大小初始时可以设置默认值,如果超过默认值时,可以重新申请更大的内存,从而达到扩容的目的。

最后,需要知道栈中实际元素的个数。来记录顺序表中最后一个元素所在的位置下标。以及与默认长度进行对比。

扩容顺序栈的结构定义:

//  扩容顺序栈的结构定义
typedef struct SeqStack
{
    int *data;   //  动态申请顺序栈的内存空间
    int size;  //  顺序栈的实际长度
    int maxlength;  //  顺序栈的最大长度
}SeqStack,*Pstack;


基本操作:(基本操作和顺序栈相同,但由于扩容顺序栈为动态开辟,则需要增加扩容操作和销毁栈的操作)

void InitStack(Pstack ps);    // 初始化栈
bool IsFull(Pstack ps);    // 判满
void Inc(Pstack ps);        // 扩容
bool Push(Pstack ps,int val);   // 入栈
bool Pop(Pstack ps,int *rtv);    // 出栈
bool GetTop(Pstack ps,int *rtv);    //得到栈顶元素(不删除)
bool IsEmpty(Pstack ps);    // 判空
void Clear(Pstack ps);    // 清空栈
void Destroy(Pstack ps)  ; //  销毁栈
void Show(Pstack ps);    // 打印
 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值