【数据结构】五分钟自测主干知识(四)

2024-03-15 1273阅读

温馨提示:这篇文章已超过370天没有更新,请注意相关的内容是否还可用!

线性数据结构中有两个典型代表——栈和队列。它们的逻辑结构和线性表一致,不同之处在于其操作的特殊性:栈的插入和删除操作只能在线性表的一端进行,并且元素遵循“后进先出”的原则

今天我们先来讲述这个经典概念:“栈”


3.1栈的基本概念

栈(Stack)是一种线性结构,是一种限定只能在表的一端进行插入和删除操作的线性表。后进入栈的元素将最先出栈,因此栈又称LIFO(Last In First Out)表。

在栈中,允许插入和删除元素的一端被称为“栈顶”(Top),另一端则称为“栈底”(Bottom)。

栈的基本操作主要是插入(入栈)和删除(出栈)操作。(都是在栈顶完成)

下面给出栈的抽象数据类型定义:

ADT Stack{

数据对象:【数据结构】五分钟自测主干知识(四)

数据关系:【数据结构】五分钟自测主干知识(四)

基本操作:

InitStack(&S)

操作结果:创建一个空的栈S。

DestroyStack(&S)

操作结果:销毁栈S。

参数说明:栈S已存在。

ClearStack(&S)

操作结果:将栈S清空。

参数说明:栈S已存在。

StackEmpty(S)

操作结果:若栈S为空则返回TRUE;否则返回FALSE。

参数说明:栈S已存在。

StackLength(S)

操作结果:返回栈S中的元素个数,即栈的长度。

参数说明:栈S已存在。

GetTop(S,&e)

操作结果:将栈S的栈顶元素的值通过e返回。

参数说明:栈S已存在且非空。

Push(&S,e)

操作结果:将e插入为栈S新的栈顶元素。

参数说明:栈S已存在。

PoP(&S,&e)

操作结果:若栈非空,删除栈S的栈顶元素,并将其值赋给e。

参数说明:栈S已存在。

StackTraverse(S)

操作结果:从栈底到栈顶依次输出S中各个元素。

参数说明:栈S已存在。

}end ADT Stack


3.2栈的表示与实现

顺序栈

与顺序表类似,顺序栈也是利用顺序存储来实现栈的。即利用一组连续的存储单元依次存放自栈底到栈顶的元素。

顺序栈一般设置一个静态指针top来表示栈顶元素在顺序栈中的位置                                              注意:这不是一个物理地址(内存指针),而是一个静态指针(即一个整型值),表示栈顶元素的数组下标。

一般用top=-1表示空栈

n个元素空间的顺序栈可以存储n个栈元素,满栈时top=n-1。

【数据结构】五分钟自测主干知识(四)

顺序栈表示如下:

typedef int ElemType;
#define STACK_INIT_SIZE 100
typedef struct {
	ElemType* elem;
	int stacksize;
	int top;
}SqStack;

下面来讲基本操作,因为都是在栈顶进行,这相对于线性表而言,都简单不少


1.顺序栈的初始化

需要给每个结构参数赋值

其中可以在msize参数中指定,也可以采用缺省值(用户未输入时的默认值STACK_INIT_SIZE)

void InitStack(SqStack& S, int msize = STACK_INIT_SIZE) {
	S.elem = new ElemType[msize];
	S.stacksize = msize;
	S.top = -1;
}

2.顺序栈的销毁

某些应用中如果栈贴别庞大,不使用了就应该及时销毁

void DestroyStack(SqStack& S) {
	delete[] S.elem;
	S.top = -1;
	S.stacksize = 0;
}

3.顺序栈获取栈顶元素

先看是不是空栈

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

4.入栈操作

将某元素插入到栈顶,作为新的栈顶元素,这称作“入栈”。

和顺序表一样,插入元素需要考虑顺序栈是否已经到达最大容量。

void Push(SqStack& S, ElemType e) {
	if (S.top == S.stacksize) {
		Increment(S);        //如果栈满则增加空间
	}
		S.elem[++S.top] = e;
}

Increment算法和顺序表的相似(见第二讲)

还是给大家展现一下吧,方便一下读者

void ErrorMsg(const char* a) {
	printf(a);        //错误处理函数,我们老熟人了,再打上去一次
}
void Increment(SqStack& S) {
	ElemType* a;
	a = new ElemType[S.stacksize + 1];//重新创建一个数组
	if (!a) { ErrorMsg("内存创建失败"); return; }
	for (int i = 0; i  

5.出栈操作 

若栈非空,将栈顶元素删除,原栈顶元素下一个元素成为新的栈顶元素。这称作“出栈”。

bool Pop(SqStack& S, ElemType& e) {
	if (S.top == -1) { return false; }
	e = S.elem[S.top--];
	return true;
}

顺序表初始化分配好最大的使用空间,如果在使用时出现栈满情况,就不得不重新分配一个更大块的连续空间,进行大批量的元素转移,因此尽量避免。

我来介绍下面的链栈,它具有比顺序栈更好的性能。


链栈

【数据结构】五分钟自测主干知识(四)

还记得我们之前(第三讲)定义了链表

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode* next;
}LNode, * LinkList;//LinkList就可以用来表示一个单链表

而我们的链栈的表示:

typedef LinkList LinkStack;

嘿嘿,完全一样(我就换个名字)

使用了一个LNode类型的指针来表示链栈,该指针指向链栈的栈顶。

基本操作如下:


1.链栈的初始化

void InitStack(LinkStack& S) {
	S = NULL;
}

2.链栈的销毁操作

不能仅仅简单地把栈顶指针置空,而是需要释放当前栈内所有元素的内存空间

(消除过期的对象引用,防止“内存泄漏”)

void DestroyStack(LinkStack& S) {
	while (S)
	{
		LNode* p = new LNode;
		p = S;
		S = S->next;//S指针后移
		delete p;
	}
}

3.链栈获取栈顶元素

bool GetTop(LinkStack& S, ElemType& e) {
	if (!S) return false;
	e = S->data;
	return true;
}

4.入栈操作

相当于单链表头插操作

void Push(LinkStack& S, ElemType e) {
	LNode* p = new LNode;
	p->data = e;
	p->next = S;
	S = p;
}

5.出栈操作 

bool Pop(LinkStack& S, ElemType& e) {
	if (!S) return false;
	LNode* p = new LNode;
	p = S;
	S = S->next;	//S删除栈顶元素
	e = p->data;
	delete p;	//释放该结点内存空间
	return true;
}

可以看出,由于栈限制了插入和删除操作只能在栈顶,用链式存储实现栈正是发挥了链表的长处,避免了链表中前插和删除需要查询前驱元素的不足。

因此,和顺序存储比较,链式存储都是实现栈的更好选择。

 


为大家精心挑选有关栈的习题在我另一个附贴上,配合食用效果更佳~

【数据结构】经典习题自测(四)

http://t.csdnimg.cn/dJOly


接下来,我们将讲述栈的孪生兄弟:队列

附链接:【数据结构】五分钟自测主干知识(五)

方便大家自取自测~

http://t.csdnimg.cn/hf1YB【数据结构】五分钟自测主干知识(四)http://t.csdnimg.cn/hf1YB

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]