栈种常见的数据结构,它用来解决一些数据类型的问题,那么好,我来带着大家来学习一下栈
文章目录
- 栈
- 对栈的认识
- 栈的模拟实现
- 栈的练习
- 方法一
- 方法二
栈
对栈的认识
栈(stack)是限定只能在表的一端进行插入删除操作的线性表
栈是一种先进后出的顺序结构,这里的先进后出就是先进来的数据要后出(跟没说一样)
就是1,2,3,4,5这五个数据,只能从5到1逐个访问。
数据结构栈的定义
栈顶:栈顶元素,最后一个入栈的元素
入栈
出栈
栈空:判断栈是否为空
栈的大小:返回站内元素个数
栈的模拟实现
在了解了栈之后,我们来对它进行简单的实现一下。
首先,我们应该先了解大框架,这里我们用数组的方式进行模拟实现(比较合适的方式,其他的也可以)
我们采用分模块的方式进行实现,这里,我在代码中会进行注释,可直接阅读代码来学习栈的实现。
stack.h用来声明各种头文件。
stack.c用来实现各个功能的实现包括入栈。 出栈等栈的基本功能。
test.h来测试代码功能
stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//栈可以村粗不同类型的数据,这里我们直接使用·typedef重定义类型
typedef int stdatetype;
//用结构体来实现栈
typedef struct stack {
int capacity;//capacity表示栈的容量
int top;//栈顶元素
int* a;//数组
}st;//st是重命名的结果
//栈的初始化
void initst(st* pst);
//栈的插入和删除
void pushback(st* pst,stdatetype x);
void popback(st* pst);
void printst(st* pst);
//返回栈顶元素
stdatetype sttop(st* pst);
//返回栈内元素个数
int sizest(st* pst);
//返回栈是否为空
bool empty(st* pst);
//销毁栈
void destroy(st* pst);
stack.c
#include"stack.h"
//初始化栈
void initst(st* pst)
{
pst->top = -1;//top初始化为-1(这里也可以是零,但下面的代码也需要改动)
//栈的容量
pst->capacity = 0;//capacity可扩容
pst->a = NULL;//对数组a进行制空
}
//入栈
void pushback(st* pst,stdatetype x)
{
assert(pst);//断言,以防止pst是一个空指针
if ((pst->top + 1) == pst->capacity)//判断,如果top+1等于栈的容量的
话,就要进行扩容
{
pst->capacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
stdatetype* tail = (stdatetype*)realloc(pst->a, sizeof(stdatetype)*pst->capacity);
assert(tail);//断言一下,如果扩容失败,终止程序
pst->a = tail;//扩容成功,把地址给a
}
pst->a[++(pst->top)] = x;//入栈
}
//出栈
void popback(st* pst)
{
assert(pst);
//如果栈为空,终止程序
assert(pst->top > -1);
pst->top--;
}
//返回栈顶元素
stdatetype sttop(st* pst)
{
assert(pst);
//栈为空终止程序
assert(pst->top > -1);
return pst->a[pst->top];//返回栈顶元素
}
//返回栈的大小
int sizest(st* pst)
{
assert(pst);
return pst->top + 1;
}
//判断栈是否为空
bool empty(st* pst)
{
assert(pst);
return pst->top == -1;//直接进行判断
}
//销毁栈
void destroy(st* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = -1;
pst->capacity = 0;
}
test.c
#include"stack.h"
int main()
{
st s;
initst(&s);
pushback(&s, 1);
pushback(&s, 2);
pushback(&s, 3);
printf("%d", sizest(&s));
popback(&s);
while (s.top > -1)
printf("%d--", s.a[s.top--]);//因为栈的特点,要这样对栈进行打印
if (empty(&s))
printf("\n空");
destroy(&s);
return 0;
}
好了,栈是比较简单的数据结构,学习到这里,相信你也已经对栈有了一定的了解,
栈的练习
下面我们来做一道题,趁热打铁一下
https://leetcode.cn/problems/valid-parentheses/description/
这是这道题的要求
这道题就非常适合使用栈来解决,当我们学完C++之后,stl库的使用会让我们更轻松的解决这道题,但是我们这里也有解决方法,我们可以直接把上面的模拟实现,稍做修改拿来使用
这里我·提供两种方法(都可以通过)
方法一
下面是这道题的代码,大部分都是在实现栈,当我们学习过C++stl之后,这就会非常简单
bool isValid(char* s) {
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef char stdatetype;
//用结构体来实现栈
typedef struct stack {
int capacity;//capacity表示栈的容量
int top;//栈顶元素
stdatetype* a;//数组
}st;//st是重命名的结果
void initst(st* pst)
{
pst->top = -1;//top初始化为-1(这里也可以是零,但下面的代码也需要改动)
//栈的容量
pst->capacity = 0;//capacity可扩容
pst->a = NULL;//对数组a进行制空
}
//入栈
void pushback(st* pst,stdatetype x)
{
assert(pst);//断言,以防止pst是一个空指针
if ((pst->top + 1) == pst->capacity)//判断,如果top+1等于栈的容量的
//话,就要进行扩容
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
stdatetype* tail = (stdatetype*)realloc(pst->a, sizeof(stdatetype)*newcapacity);
assert(tail);//断言一下,如果扩容失败,终止程序
pst->a = tail;//扩容成功,把地址给a
pst->capacity=newcapacity;
}
pst->a[++(pst->top)] = x;//入栈
}
//出栈
void popback(st* pst)
{
assert(pst);
//如果栈为空,终止程序
assert(pst->top > -1);
pst->top--;
}
//返回栈顶元素
stdatetype sttop(st* pst)
{
assert(pst);
//栈为空终止程序
assert(pst->top > -1);
return pst->a[pst->top];//返回栈顶元素
}
//返回栈的大小
int sizest(st* pst)
{
assert(pst);
return pst->top + 1;
}
//判断栈是否为空
bool empty(st* pst)
{
assert(pst);
return pst->top == -1;//直接进行判断
}
//销毁栈
void destroy(st* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = -1;
pst->capacity = 0;
}
st _st;
initst(&_st);
while(*s)
{
char ch=*s;
if(ch=='{'||ch=='('||ch=='[')
{
pushback(&_st,ch);
}
else
{
if(_st.top==-1){
destroy(&_st);//防止内存泄露
return false;
}
if((ch=='}'&&sttop(&_st)!='{')||
(ch==')'&&sttop(&_st)!='(')||
(ch==']'&&sttop(&_st)!='['))
{
destroy(&_st);
return false;
}
popback(&_st);
}
s++;
}
if(!empty(&_st)){
destroy(&_st);
return false;
}
destroy(&_st);
return true;
}
方法二
这样的实现过于麻烦,我们也有另一种方法,用数组快速的模拟栈
直接看代码吧
bool isValid(char* s) {
const int N = 10010;
int st[N];
int hh=0;
while(*s)
{
char top=*s;
if(top=='{'||top=='('||top=='[')
{
st[hh++]=top;
}
else
{
if(hh==0)
return false;
if((top=='}'&&st[hh-1]!='{')||
(top==')'&&st[hh-1]!='(')||
(top==']'&&st[hh-1]!='['))
{
return false;
}
hh--;
}
s++;
}
if(hh)
{
return false;
}
return true;
}
栈的学习就先到这里了,各位有什么不同见解可以说出来,一起交流一下
感谢观看,有错误请指出