【数据结构与算法】栈的介绍与实现(详解)

1.1栈的概念及结构

一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶
在这里插入图片描述

了解进栈·出栈规则我们来看两个题:
在这里插入图片描述
第一题遵循后进先出原则,很显然选B
我们来具体看一下第二题:

A选项 在这里插入图片描述
故A选项成立

B选项 在这里插入图片描述
故B选项成立

C选项: 在这里插入图片描述
故C选项错误

D选项: 在这里插入图片描述
故D选项成立

1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小,但是数组的缺点是需要增容。
在这里插入图片描述

具体实现:

在这里插入图片描述

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDatatype;//栈中存储的元素类型(这里用整型举例)

//首先,我们需要用结构体创建一个栈,这个结构体需要包括栈的基本内容(栈,栈顶,栈的容量)。
typedef struct Stack
{
	STDatatype* a;//栈
	int top;//栈顶
	int capacity;//容量,方便增容
}ST;

// 初始化栈
void StackInit(ST* ps);

// 销毁栈
void StackDestory(ST* ps);

// 入栈
void StackPush(ST* ps,STDatatype x);

// 出栈
void StackPop(ST* ps);

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(ST* ps);

// 获取栈中有效元素个数
int  StackSize(ST* ps);

// 获取栈顶元素
STDatatype StackTop(ST* ps);

在这里插入图片描述

#include"Stack.h"
//初始化栈
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//销毁栈
//栈的内存空间是动态开辟出来的,当我们使用完后必须释放其内存空间,避免内存泄漏
void StackDestory(ST* ps)
{
	assert(ps);
	if (ps->a)
	{
		free(ps->a);//释放栈
	}
	ps->a = NULL;
	ps->top = 0;//-1也可以 //栈顶置0
	ps->capacity = 0;//容量置0
}

//入栈
//进行入栈操作前,我们需要检测栈的当前状态,若已满,则需要先对其进行增容,然后才能进行入栈操作
void StackPush(ST* ps, STDatatype x)
{
	assert(ps);
	//检查空间够不够,不够就增容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDatatype* tmp = realloc(ps->a, sizeof(STDatatype) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail!\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;//栈顶位置存放元素x
	ps->top++;//栈顶上移
}

//出栈
void StackPop(ST* ps)//删数据
{
	assert(ps);
	assert(!StackEmpty(ps));//检测栈是否为空
	--ps->top;//栈顶下移
}

//检测栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//获取栈中有效元素个数
int  StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//获取栈顶元素
//top记录的是栈顶,使用top的值便代表栈中有效元素的个数
STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));//检测栈是否为空

	return ps->a[ps->top - 1];//返回栈顶元素
}

简单测试:
在这里插入图片描述

#include"Stack.h"
int main()
{
	ST st;
	StackInit(&st);
	StackPush(&st,1);
	StackPush(&st,2);
	StackPush(&st,3);
	StackPush(&st,4);
	StackPush(&st,5);
	//若栈非空,逐个获取栈顶元素,出栈
	while (!StackEmpty(&st))

	{
		printf("%d", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");

	StackDestory(&st);

	return 0;
}

运行结果:

在这里插入图片描述
(遵循后进先出)

1.3栈经典例题<-(戳这里)

在这里插入图片描述

根据题意,可利用栈解决

思路:
建立栈,遇到左括号入栈,遇到右括号,让入栈的左括号的栈顶数据(左括号)对应的右括号和遇到的右括号进行匹配,若相等,接着匹配,直到证明字符串有效,只要匹配时遇到不相等,则字符串无效。

代码实现:

1.先将我们我们之前写的栈原封不动拿过来:

注意:要将栈中存储的元素类型该为char

typedef char STDatatype;//栈中存储的元素类型
typedef struct Stack
{
	STDatatype* a;//栈
	int top;//栈顶
	int capacity;//容量,方便增容
}ST;
// 初始化栈
void StackInit(ST* ps);

// 销毁栈
void StackDestory(ST* ps);

// 入栈
void StackPush(ST* ps,STDatatype x);

// 出栈
void StackPop(ST* ps);

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(ST* ps);

// 获取栈中有效元素个数
int  StackSize(ST* ps);

// 获取栈顶元素
STDatatype StackTop(ST* ps);

//初始化栈
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//销毁栈
void StackDestory(ST* ps)
{
	assert(ps);
	if (ps->a)
	{
		free(ps->a);//释放栈
	}
	ps->a = NULL;
	ps->top = 0;//-1也可以 //栈顶置0
	ps->capacity = 0;//容量置0
}

//入栈
void StackPush(ST* ps, STDatatype x)
{
	assert(ps);
	//检查空间够不够,不够就增容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDatatype* tmp = realloc(ps->a, sizeof(STDatatype) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail!\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;//栈顶位置存放元素x
	ps->top++;//栈顶上移
}

//出栈
void StackPop(ST* ps)//删
{
	assert(ps);
	assert(!StackEmpty(ps));//检测栈是否为空
	--ps->top;//栈顶下移
}

//检测栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//获取栈中有效元素个数
int  StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//获取栈顶元素
STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));//检测栈是否为空

	return ps->a[ps->top - 1];//返回栈顶元素
}

2.逻辑实现:

bool isValid(char * s){
ST st;
StackInit(&st);
bool match=true;
while(*s)
{
    if(*s=='['||*s=='('||*s=='{')
    {
        StackPush(&st,*s);
        ++s;
    }
    else
    {
        if(StackEmpty(&st))
        {
            match=false;
            break;
        }
        char ch=StackTop(&st);
        StackPop(&st);
        if((*s==']'&&ch!='[')||(*s=='}'&&ch!='{')||(*s==')'&&ch!='('))
        {
match=false;
break;
        }
        else{
            ++s;
        }
    }
}
if(match==true)
{
    match=StackEmpty(&st);
}
StackDestory(&st);
return match;
}

– the End –

以上就是我分享的【栈的介绍与实现】相关内容,感谢阅读!

本文收录于专栏C++
关注作者,持续阅读作者的文章,学习更多知识!
https://blog.csdn.net/weixin_53306029?spm=1001.2014.3001.5343

2021/11/20
————————————————

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
数据结构是计算机存储、组织数据的方式,算法是解决问题的步骤和方法。数据结构和算法是计算机科学中最基础、最重要的两个领域之一。掌握数据结构和算法可以帮助我们更好地理解计算机科学的本质,提高编程能力,解决实际问题。 常见的数据结构包括数组、链表、、队列、树、图等。常见的算法包括排序、查找、递归、分治、动态规划等。 在学习数据结构和算法时,需要掌握以下知识点: 1. 时间复杂度和空间复杂度:用来衡量算法的效率和资源消耗。 2. 数组:一种线性数据结构,用来存储一组相同类型的元素。 3. 链表:一种线性数据结构,用来存储一组元素,每个元素包含一个指向下一个元素的指针。 4. :一种后进先出(LIFO)的数据结构,用来存储一组元素。 5. 队列:一种先进先出(FIFO)的数据结构,用来存储一组元素。 6. 树:一种非线性数据结构,由节点和边组成,每个节点可以有多个子节点。 7. 图:一种非线性数据结构,由节点和边组成,每个节点可以有多个相邻节点。 8. 排序算法:用来将一组元素按照一定的顺序排列的算法,包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。 9. 查找算法:用来在一组元素中查找指定元素的算法,包括线性查找、二分查找、哈希查找等。 10. 递归算法:一种通过调用自身来解决问题的算法。 11. 分治算法:一种将问题分解成多个子问题来解决的算法。 12. 动态规划算法:一种通过将问题分解成多个子问题来解决的算法,通常用于求解最优化问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

…狂奔的蜗牛~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值