目录
栈的实现
栈后入先出
1、数组栈
(最佳实现,且访问数据的时候CPU告诉访存命中率比较高,因为地址连续存放,访问时CPU从cache里一次访问一片)
数组适合尾插尾删,所以栈底在数组头部
2、链式栈
双向链表,栈底可以是尾也可以是头
单链表,头插头删方便,所以栈顶在链表尾部
(单链表的头插头删方便在:
头插:加减新节点只需要修改头指针指向新的节点,时间复杂度通常是O(1)
尾插:需要遍历整个链表才能找到最后一个节点并将其之后的位置设置为新节点或者释放结点,时间复杂度是O(n)
栈的创建
栈的打印
以下是单链表的打印
此为栈的打印
栈访问一遍就已经空了
内存泄漏
后端开发,比如游戏上线了之后除了升级就不能退出,所以如果存在内存泄漏就会导致游戏越来越慢,因为可用内存资源越来越少
如果是在前端操作系统里出现了内存泄漏的情况,在进程结束掉之后就会主动释放空间,所以危害性不大
栈溢出
指的是给这个栈划分的内存区域爆了,比如写了一个死循环的递归
练习
有效的括号
数量和顺序都要匹配
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char STDataType;
typedef struct Stack {
STDataType* a;
int top;//标识栈顶位置
int capacity;//容量
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst) {
assert(pst);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
void STDestroy(ST* pst) {
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
void STPush(ST* pst, STDataType x) {
assert(pst);
if (pst->top == pst->capacity) {
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (tmp == NULL) {
perror("relloc");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
//在a[0]的时候放入第一个值
pst->top++;
}
void STPop(ST* pst) {
assert(pst);
assert(pst->top > 0);//不为空
pst->top--;
}
STDataType STTop(ST* pst) {
assert(pst);
assert(pst->top > 0);//不为空
return pst->a[pst->top - 1];
}
bool STEmpty(ST* pst) {
assert(pst);
return pst->top == 0;
//等于0返回真,不等于0返回假
}
int STSize(ST* pst) {
assert(pst);
return pst->top;
}
bool isValid(char* s) {
ST st;
STInit(&st);
while(*s){
if(*s == '{' || *s == '[' || *s == '('){
//*s是左括号就入栈
STPush(&st, *s);
}
else{
//右比左多,会导致循环时栈为空,还要弹栈
if(STEmpty(&st)){
//防止内存泄漏
STDestroy(&st);
return false;
}
//*s是右括号就与栈顶匹配
char top = STTop(&st);
STPop(&st);
//检查顺序匹配
if((*s == '}' && top != '{')
||(*s == ']' && top != '[')
||(*s == ')' && top != '(')){
STDestroy(&st);
return false;
}
}
++s;
}
//检查数量匹配
//左多右少
bool ret = STEmpty(&st);
//等于0就返回真,不等于0就返回假
STDestroy(&st);
return ret;
}