目录
1.栈
2.实现
3.OJ题
1. 栈
1. 栈的概念和结构
栈: 这一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
压栈: 栈的插入操作叫做压栈/入栈进栈,数据在栈顶
出栈: 栈的删除操作叫出栈,数据也在栈顶
选择题
第一个题依次入栈,那么出栈的顺序就是相反的,E是第一个,1是最后一个
第二题不可能的出栈顺序,想3先出栈,3前面的都得入栈,3出完栈后必须2出栈,所以C不可能
2. 实现
栈的实现可以用数组或者链表,相对而言数组的机构更优一些,因为数组尾插的代价更小
所以将数组的尾巴作为栈顶,0下标作为栈底
在结构体设计中,top代表栈顶的位置,初始化为0,代表下一个栈顶数据的位置。出栈和栈顶元素需要判断是不是空栈
头文件
c
#pragma once
#include <stdbool.h>
typedef int DATATYPE;
typedef struct _Stack
{
DATATYPE* ary;
int top; //指向下一个存放数据的位置
int capacity;
}Stk;
//初始化
void Init(Stk* stack);
//入栈
void Push(Stk* stack, DATATYPE data);
//出栈
void Pop(Stk* stack);
//显示栈顶元素
DATATYPE Top(Stk* stack);
//栈大小
int Size(Stk* stack);
//是否为空
bool Empty(Stk* stack);
//销毁
void Destory(Stk* stack);
实现文件
c
#include "Stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void Init(Stk* stack)
{
assert(stack);
stack->ary = NULL;
stack->top = 0; //指向栈顶下一个位置
stack->capacity = 0;
}
void Push(Stk* stack, DATATYPE data)
{
assert(stack);
//需要扩容
if (stack->top == stack->capacity)
{
int newcap = stack->capacity == 0 ? 4 : stack->capacity * 2;
DATATYPE* temp = (DATATYPE*)realloc(stack->ary, sizeof(newcap) * newcap);
if (temp == NULL)
{
perror("realloc fail");
return;
}
stack->ary = temp;
stack->capacity = newcap;
}
//存数据
stack->ary[stack->top] = data;
stack->top++;
}
bool Empty(Stk* stack)
{
assert(stack);
return stack->top == 0;
}
void Pop(Stk* stack)
{
assert(stack);
assert(!Empty(stack));
stack->top--;
}
DATATYPE Top(Stk* stack)
{
assert(stack);
assert(!Empty(stack));
return stack->ary[stack->top - 1];
}
int Size(Stk* stack)
{
assert(stack);
return stack->top;
}
void Destory(Stk* stack)
{
assert(stack);
free(stack->ary);
stack->ary = NULL;
stack->capacity = 0;
stack->top = 0;
}
主文件
c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Stack.h"
int main()
{
Stk st;
Init(&st);
Push(&st, 1);
Push(&st, 2);
Push(&st, 3);
Push(&st, 4);
while (!Empty(&st))
{
printf("->%d ", Top(&st));
Pop(&st);
}
Destory(&st);
return 0;
}
3.OJ题
有效的括号: https://leetcode.cn/problems/valid-parentheses/description/
思路
有两个不匹配,一个是数量不匹配,一个是内容不匹配。这个题可以利用栈结构,遇到左括号入栈,右括号出栈。出栈会自动匹配栈顶元素,也就是离的最近的括号,如果两个括号不匹配,说明不满足,也就是内容不匹配。如果出栈时栈为空或者字符串遍历完栈不为空,说明都是数量不匹配。C语言解决这个题最简单的方法就是先实现一个栈,直接调用栈结构,因为栈里面有栈顶、是否为空这些函数可以直接利用
c
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef char DATATYPE;
typedef struct _Stack {
DATATYPE* ary;
int top; //指向下一个存放数据的位置
int capacity;
} Stk;
void Init(Stk* stack) {
assert(stack);
stack->ary = NULL;
stack->top = 0; //指向栈顶下一个位置
stack->capacity = 0;
}
void Push(Stk* stack, DATATYPE data) {
assert(stack);
//需要扩容
if (stack->top == stack->capacity) {
int newcap = stack->capacity == 0 ? 4 : stack->capacity * 2;
DATATYPE* temp =
(DATATYPE*)realloc(stack->ary, sizeof(newcap) * newcap);
if (temp == NULL) {
perror("realloc fail");
return;
}
stack->ary = temp;
stack->capacity = newcap;
}
//存数据
stack->ary[stack->top] = data;
stack->top++;
}
bool Empty(Stk* stack) {
assert(stack);
return stack->top == 0;
}
void Pop(Stk* stack) {
assert(stack);
assert(!Empty(stack));
stack->top--;
}
DATATYPE Top(Stk* stack) {
assert(stack);
assert(!Empty(stack));
return stack->ary[stack->top - 1];
}
int Size(Stk* stack) {
assert(stack);
return stack->top;
}
void Destory(Stk* stack) {
assert(stack);
free(stack->ary);
stack->ary = NULL;
stack->capacity = 0;
stack->top = 0;
}
bool isValid(char* s) {
Stk st;
Init(&st);
while (*s != '\0') {
//左括号入栈
if (*s == '(' || *s == '[' || *s == '{') {
Push(&st, *s);
} else
//右括号出栈
{
//返回前销毁栈
if (Empty(&st)) {
Destory(&st);
return false;
}
char ch = Top(&st);
if ((*s == ')' && ch != '(') || (*s == ']' && ch != '[') ||
(*s == '}' && ch != '{')) {
Destory(&st);
return false;
}
Pop(&st);
}
s++;
}
//栈不为空 数量不匹配
if (!Empty(&st)) {
Destory(&st);
return false;
}
Destory(&st);
return true;
}