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



















