1. 栈·模型
受限的线性表,只能在一端添加,在同一端删除。满足LIFO
2. 栈·API
入栈、出栈,查看栈顶元素、判空
3. 栈的实现
3.1 栈的链表实现
①Stack.h
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
// 定义结点类型
typedef struct node {
int val;
struct node* next;
} Node;
// API
void stack_push(Node** pstack, int val);
int stack_pop(Node** pstack);
int stack_peek(Node* stack);
bool stack_empty(Node* stack);
②Stack.c
#include"Stack.h"
void stack_push(Node** pstack, int val) {
Node* newNode = malloc(sizeof(Node));
if (!newNode) {
printf("failed.\n");
exit(1);
}
newNode->val = val;
newNode->next = *pstack;
*pstack = newNode;
}
int stack_pop(Node** pstack) {
if (stack_empty(*pstack)) {
printf("stack is empty.\n");
exit(1);
}
Node* curr = *pstack;
int ret = curr->val;
*pstack = (*pstack)->next;
free(curr);
return ret;
}
int stack_peek(Node* stack) {
if (stack_empty(stack)) {
printf("stack is empty.\n");
exit(1);
}
return stack->val;
}
bool stack_empty(Node* stack) {
//if (stack == NULL) {
// return 1;
//} else {
// return 0;
//}
return stack == NULL;
}
③main.c
#include"Stack.h"
int main(void) {
// Node node1;
// Node* pnode1 = &node1;
// Node** pstack = pnode1;
Node* stack = NULL;
stack_push(&stack, 1);
stack_push(&stack, 2);
stack_push(&stack, 3);
stack_push(&stack, 4);
int topVal = stack_peek(stack);
stack_pop(&stack);
stack_pop(&stack);
stack_pop(&stack);
bool isempty = stack_empty(stack);
stack_pop(&stack);
isempty = stack_empty(stack);
return 0;
}
3.2 栈的数组实现
①Stack.h
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
// 定义结点类型
typedef struct {
int* elements;
int size;
int capacity;
} Stack;
// API
void stack_push(Stack* stack, int val);
int stack_pop(Stack* stack);
int stack_peek(Stack* stack);
bool stack_empty(Stack* stack);
②Stack.c
#include"Stack.h"
#define DEFAULT_CAPACITY 8
#define THRESHOLD 4094
// API
void grow_capacity(Stack* s) {
//确定new_capacity
int new_capacity;
if (s->capacity == 0) {
new_capacity = DEFAULT_CAPACITY;
}else if (s->capacity <= THRESHOLD) {
new_capacity = s->capacity << 1;
} else {
new_capacity = s->capacity + (s->capacity >> 1);
}
//扩容操作
int* p = realloc(s->elements, new_capacity * sizeof(int));
if (!p) {
printf("realloc failed in grow_capacity.\n");
exit(1);
}
s->elements = p;
s->capacity = new_capacity;
}
void stack_push(Stack* stack, int val) {
if (stack->size == stack->capacity) {
grow_capacity(stack);
}
stack->elements[stack->size] = val;
stack->size++;
}
int stack_pop(Stack* stack) {
if (stack->size == 0) {
printf("stack is empty.\n");
exit(1);
}
stack->size--;
return stack->elements[stack->size];
}
int stack_peek(Stack* stack) {
if (stack->size == 0) {
printf("stack is empty.\n");
exit(1);
}
return stack->elements[stack->size - 1];
}
bool stack_empty(Stack* stack) {
return stack->size == 0;
}
③main.c
#include"Stack.h"
int main(void) {
Stack* newStack = calloc(1,sizeof(Stack));
stack_push(newStack, 1);
stack_push(newStack, 2);
stack_push(newStack, 3);
stack_push(newStack, 4);
int topVal = stack_peek(newStack);
stack_pop(newStack);
stack_pop(newStack);
stack_pop(newStack);
bool isempty = stack_empty(newStack);
stack_pop(newStack);
isempty = stack_empty(newStack);
return 0;
}
4. 栈的使用场景
① 函数调用栈
② 符号匹配问题
③ 表达式求值:
用栈将中缀表达式转为后缀表达式:运算符入栈,入栈前将栈中优先级比自己大或相同的运算符依次输出,数字直接输出不入栈
由后缀表达式,计算算式的值:遇到数字直接入栈,遇到运算符时,在栈中去除两个数字进行计算,结果再存入栈中。最后栈中的元素即为结果
④ 深度优先搜索:图的拓朴排序