栈种常见的数据结构,它用来解决一些数据类型的问题,那么好,我来带着大家来学习一下栈
文章目录
- 栈
- 对栈的认识
- 栈的模拟实现
- 栈的练习
- 方法一
- 方法二
栈
对栈的认识
栈(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;//扩容成功,把地址给apst->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;
}
栈的学习就先到这里了,各位有什么不同见解可以说出来,一起交流一下
感谢观看,有错误请指出