数据结构——栈和队列(C语言)

栈种常见的数据结构,它用来解决一些数据类型的问题,那么好,我来带着大家来学习一下栈

文章目录

    • 对栈的认识
    • 栈的模拟实现
    • 栈的练习
      • 方法一
      • 方法二

对栈的认识

栈(stack)是限定只能在表的一端进行插入删除操作的线性表

栈是一种先进后出的顺序结构,这里的先进后出就是先进来的数据要后出(跟没说一样)
就是1,2,3,4,5这五个数据,只能从5到1逐个访问。

数据结构栈的定义

栈顶:栈顶元素,最后一个入栈的元素
入栈
出栈
栈空:判断栈是否为空
栈的大小:返回站内元素个数

栈的模拟实现

在了解了栈之后,我们来对它进行简单的实现一下。
首先,我们应该先了解大框架,这里我们用数组的方式进行模拟实现(比较合适的方式,其他的也可以)

我们采用分模块的方式进行实现,这里,我在代码中会进行注释,可直接阅读代码来学习栈的实现。

stack.h用来声明各种头文件。
stack.c用来实现各个功能的实现包括入栈。 出栈等栈的基本功能。
test.h来测试代码功能

stack.h

#pragma once

#include
#include
#include
#include

//栈可以村粗不同类型的数据,这里我们直接使用·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语言)_第1张图片
这是这道题的要求
数据结构——栈和队列(C语言)_第2张图片

这道题就非常适合使用栈来解决,当我们学完C++之后,stl库的使用会让我们更轻松的解决这道题,但是我们这里也有解决方法,我们可以直接把上面的模拟实现,稍做修改拿来使用

这里我·提供两种方法(都可以通过)

方法一

下面是这道题的代码,大部分都是在实现栈,当我们学习过C++stl之后,这就会非常简单

bool isValid(char* s) {
    #include
#include
#include
#include
    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;
}

栈的学习就先到这里了,各位有什么不同见解可以说出来,一起交流一下

感谢观看,有错误请指出

数据结构——栈和队列(C语言)_第3张图片

你可能感兴趣的:(数据结构,c语言)