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

汇总代码见:登录 - Gitee.com

上一篇文章:数据结构:双向链表-CSDN博客

与本文相关的结构体传参:自定义类型:结构体-CSDN博客

1.栈

1.1概念和结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。
压栈: 栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈: 栈的删除操作叫做出栈。出数据也在栈顶

栈底层结构选型:

栈的实现一般可以使用数组或者链表实现,相对而言,数组的结构实现更优一些。

原因:在入栈和出栈的时间复杂度均为O(1)的前提条件下,数组的内存利用率远高于链表,尤其是在存储小数据类型时。

1.2栈的实现

依旧建立三个文件:

1.2.1定义栈的结构

复制代码
//定义栈的结构
typedef int STDataType;
typedef struct Stack {
	STDataType* arr;
	int top;//指向当前栈顶元素的索引--正好为栈中有效的数据个数
	int capacity;//栈的空间大小
}ST;

1.2.2初始化

复制代码
//初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

调用调试:

1.2.3销毁

复制代码
//销毁
void STDesTroy(ST* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

1.2.4入栈

复制代码
// ⼊栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	//判断空间是否足够
	if (ps->top == ps->capacity)
	{
		//增容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
}

调用测试:

复制代码
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
STPush(&st, 5);

1.2.5判空

复制代码
//栈是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

1.2.6出栈

复制代码
//出栈
void STPop(ST* ps)
{
	assert(!STEmpty(ps));
	ps->top--;
}

调用测试:

1.2.7取栈顶元素

top为指向当前栈顶元素的索引,所以需要-1。

复制代码
//取栈顶元素
STDataType STTop(ST* ps)
{
	assert(!STEmpty(ps));
	return ps->arr[ps->top - 1];
}

调用测试:

复制代码
while (!STEmpty(&st))
{
	//取栈顶
	STDataType top = STTop(&st);
	printf("%d ", top);
	//出栈
	STPop(&st);
}
printf("\n");

1.2.8获取栈中有效元素个数

复制代码
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

调用测试:

复制代码
printf("size:%d\n",STSize(&st));

1.3解释assert(ps)与assert(!STEmpty)

assert(ps):保证传入的为有效的栈结构体变量。限制参数不能为空。

assert(!STEmpty):保证栈中的有效个数不能为空。

2.力扣算法题:有效的括号

20. 有效的括号 - 力扣(LeetCode)

理解题意:

思路:借助栈,遍历字符串,如果遇到左括号,就将字符串入栈,如果遇到右括号,就取栈顶,将其与右括号相比较,相同则出栈。

编程中遇到的问题:有空字符串或者遇到一开始就是右括号的,需要判断栈是否为空以及对于条件表达式的使用错误。

代码如下:

复制代码
// 需要借助栈
// 定义栈的结构
typedef char STDataType;
typedef struct Stack {
    STDataType* arr;
    int top;      // 指向当前栈顶元素的索引--正好为栈中有效的数据个数
    int capacity; // 栈的空间大小
} ST;
// 初始化
void STInit(ST* ps) {
    ps->arr = NULL;
    ps->capacity = ps->top = 0;
}

// 销毁
void STDesTroy(ST* ps) {
    if (ps->arr)
        free(ps->arr);
    ps->arr = NULL;
    ps->top = ps->capacity = 0;
}

// ⼊栈
void STPush(ST* ps, STDataType x) {
    assert(ps);
    // 判断空间是否足够
    if (ps->top == ps->capacity) {
        // 增容
        int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
        STDataType* tmp =
            (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
        if (tmp == NULL) {
            perror("realloc fail!");
            exit(1);
        }
        ps->arr = tmp;
        ps->capacity = newCapacity;
    }
    // 空间足够
    ps->arr[ps->top++] = x;
}

// 栈是否为空
bool STEmpty(ST* ps) {
    assert(ps);
    return ps->top == 0;
}

// 出栈
void STPop(ST* ps) {
    assert(!STEmpty(ps));
    ps->top--;
}

// 取栈顶元素
STDataType STTop(ST* ps) {
    assert(!STEmpty(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* i = s;
    while (*i != '\0') {
        // 左括号入栈
        if (*i == '(' || *i == '[' || *i == '{') {
            STPush(&st, *i);
        } else {
            // 右括号取栈顶,出栈或返回false
            // 若第一个为右括号,为空栈
            if (STEmpty(&st)) {
                STDesTroy(&st);
                return false;
            }
            char top = STTop(&st);
            if((top == '[' && *i != ']') 
            || (top == '{' && *i != '}')
            || (top == '(' && *i != ')'))
            {
                STDesTroy(&st);
                return false;
            } 
            //匹配-出栈
            STPop(&st);
        }
        i++;
    }
    // 栈是否为空
    //  if(STEmpty(&st))
    //  {
    //      STDesTroy(&st);
    //      return true;
    //  }
    // STDesTroy(&st);
    // return false;
    bool ret = STEmpty(&st) ? true : false;
    STDesTroy(&st);
    return ret;
}

最终通过测试。

本章完。

相关推荐
海梨花5 小时前
字节跳动后端 一面凉经
java·redis·学习·leetcode·面经
墨染点香5 小时前
LeetCode 刷题【62. 不同路径】
算法·leetcode·职场和发展
艾醒5 小时前
大模型面试题剖析:大模型微调数据集构建
人工智能·算法·程序员
CoovallyAIHub5 小时前
YOLO-ELA:用于高性能实时绝缘子缺陷检测的高效局部注意力建模
深度学习·算法·计算机视觉
一起努力啊~5 小时前
算法题打卡力扣第3题:无重复字符的最长子串(mid)
算法·leetcode·哈希算法
古译汉书6 小时前
蓝桥杯算法之基础知识(6)
数据结构·算法·蓝桥杯
熙客6 小时前
基础思想:动态规划与贪心算法
算法·贪心算法·动态规划
Liverpool05196 小时前
代码随想录算法训练营第四十三天|LeetCode300. 最长递增子序列,LeetCode674. 最长连续递增序列,LeetCode718. 最长重复子数组
算法
HCl__盐酸6 小时前
题解:UVA1589 象棋 Xiangqi
算法