数据结构:栈和队列详解(上)

一.栈

1.概念与结构:

栈:一种特殊的线性表,只允许在顺序表的一段插入和删除数据,进行插入和删除的一端叫做栈顶,另外一端则叫做栈底,而我们将在栈顶插入数据叫做压栈(入栈或进栈),在栈底删除数据则叫做出栈

栈的实现可以通过链表和数组实现,但数组在尾插时相对于需要遍历链表才能尾插的链表结构而言拥有更小的时间复杂度,所以栈的实现一般使用数组实现

2.栈的实现:

cs 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;      //指向栈顶的位置
	int capacity;//栈的容量
}ST;

//栈的初始化
void STInit(ST* ps);
//栈的销毁
void STDestory(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//判断栈是否为空(配合确定top--至0(栈底)的限制条件)
bool StackEmpty(ST* ps);
//出栈
void StackPop(ST* ps);
//取栈顶数据
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
STDataType STsize(ST* ps);
cs 复制代码
//栈的初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//栈的销毁
void STDestory(ST*ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//空间不够
	if (ps->capacity == ps->top)
	{
		//扩容
		STDataType newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
	ps->capacity++;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
	--ps->capacity;
}
//获取栈顶元素
STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top-1];
}
//获取栈中元素个数
STDataType STsize(ST* ps)
{
	assert(ps);
	return ps->top;
}

以上是栈的实现中所有涉及的函数及函数实现

3.与栈有关的算法题(有效的括号):

原题来源:https://leetcode.cn/problems/valid-parentheses/description/
这题的主要思路就是通过创建一个栈,然后在对输入的一串字符串进行遍历入栈,首先是使其中的一个栈的入栈条件为"是左括号",如果遍历出的下一个是与之对应的右括号,则使先前入栈的左括号出栈,以此类推,直至字符串遍历完成,如果此时栈为空,则说明字符串符符合题意并且返回true,若不为空,则返回false,整体来看,代码总体上会以字符串的遍历以及栈的输入输出为整体架构,并且伴随着对特殊情况1:"空栈"和特殊情况2:"字符串遍历完后栈中是否还有元素残留"的讨论,前者应当置于字符串遍历过程中字符元素与栈元素的对比之前,因为对比就意味着要从栈里读取元素,而空栈是无法读取的,后者则应当置于尾部,在对比机制完整之后以防止"【】{"(类似这种情况)的产生,同时还有一点值得注意的就是每次排除一种错误情况时都不要忘记销毁栈(因为栈的插入涉及到对空间的申请,而不及时释放空间就很容易产生内存泄漏问题)

cs 复制代码
//栈的初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//栈的销毁
void STDestory(ST* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//空间不够
	if (ps->capacity == ps->top)
	{
		//扩容
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
	ps->capacity++;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
	--ps->capacity;
}
//获取栈顶元素
char StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
//获取栈中元素个数
int STsize(ST* ps)
{
	assert(ps);
	return ps->top;
}








bool isValid(char* s) {
ST st;
STInit(&st);
char* pi = s;
//遍历字符串
while (*pi != '\0')
{

    //左括号入栈
    if (*pi == '{' || *pi == '[' || *pi == '(')
    {
        StackPush(&st, *pi);
    }
    else
    {//右括号取栈顶并匹配
    //先判断是否为空
        if (StackEmpty(&st))
        {
            STDestory(&st);
            return false;
        }
        char tmp = StackTop(&st);
        if (tmp == '{' && *pi! = '}' || tmp == '(' && *pi! = ')' || tmp == '[' && *pi! = ']')
        {
            STDestory(&st);
            return false;
        }
        StackPop(&st);
    }
    pi++;
}
//如果栈为空,说明所有的括号都匹配完了,反之为非有效字符串
bool ret = StackEmpty(&st) ? true : false;
STDestory(&st);
return ret;
}
相关推荐
pystraf9 分钟前
P9069 [Ynoi Easy Round 2022] 堕天作战 TEST_98 Solution
数据结构·c++·算法
daiwoliyunshang19 分钟前
二叉树--堆排序
数据结构·算法
脏脏a39 分钟前
【数据结构篇】顺序表 超详细
c语言·数据结构·算法
汤姆和杰瑞在瑞士吃糯米粑粑1 小时前
【C++学习篇】滑动窗口--结合例题讲解思路
开发语言·数据结构·c++·算法·散列表
mljy.2 小时前
C++《AVL树》
数据结构·c++
不玩return的马可乐3 小时前
蓝桥杯 单词重排
开发语言·数据结构·c++·算法·leetcode·职场和发展·蓝桥杯
被二进制支配的打工人3 小时前
【STL】list 双向循环链表的使用介绍
数据结构·c++·链表·stl·list
比特在路上3 小时前
StackOrQueueOJ3:用栈实现队列
c语言·开发语言·数据结构·1024程序员节
Geometry Fu4 小时前
二叉树删除子树 (题目分析+C++代码实现)
数据结构·算法·图论
一缕叶4 小时前
P8772 [蓝桥杯 2022 省 A] 求和
数据结构·c++·算法