文章目录
栈
定义
- FILO LIFO
- 先进后出,后进先出
- 链式栈(链表实现的栈) 顺序栈(顺序表实现的栈)
- 动态栈(链式栈) 和 静态栈(有内存大小限制,顺序栈)
- 栈应用非常广泛
顺序静态栈
- 内存有限
typedef int ElemType;
struct Stack {
size_t cap; // 容量
size_t size; // 元素个数
ElemType *elems;
};
typedef struct Stack* ST;
链栈
- 动态的
struct Node {
struct Node *next;
char elem[];
};
struct Stack {
size_t elemSize; // 存储的元素类型的字节数
size_t size;
struct Node *top; // 指向栈顶元素
};
typedef struct Stack* ST;
比较顺序栈和链式栈
项目 | 顺序栈 | 链式栈 |
---|---|---|
压入/弹出 时间复杂度 | O(1) 顺序栈如果是动态的可扩容就不能保证时间复杂度为O(1) | O(1) |
是否会满 | 会 | 不会 |
- 用一个数组来表示两个栈,如果要保证内存的利用最大化
- 一个栈底为0,另一个栈底为n - 1
栈的应用
- 函数调用的过程的,确实原理就是栈
- 调用函数即把函数入栈,每次执行的函数都是栈顶的这个函数,执行完成之后出栈
走迷宫
- 走迷宫
算数表达式求解
- 算数表达式求解
- 前缀表达式
- 中缀表达式
- 后缀表达式
中缀:(3 + 4) * (5 + 2 * 3) - (3 - 2) / 4; 运算符在操作数中间
后缀:3 4 + 5 2 3 * + * 3 2 - 4 / -
八皇后问题
- 八皇后问题
国际象棋棋盘8*8 皇后: 横 竖 斜
需要在棋盘上摆放8个皇后,是她们互不威胁
回溯
拆解正整数
- 拆解正整数
5 = 1 + 1 + 1 + 1 + 1
5 = 1 + 1 + 1 + 2
5 = 1 + 2 + 2
5 = 1 + 4
5 = 2 + 3
7 = 1 + 1 + 1 + 1 + 1 + 1 + 1
7 = 1 + 1 + 1 + 1 + 1 + 2
7 + 1 + 1 + 1 + 1 + 3
7 = 1 + 1 + 1 + 2 + 2
7 = 1 + 1 + 1 + 4
7 = 1 + 1 + 2 + 3
7 = 1 + 2 + 2 + 2
7 = 1 + 1 + 5
7 + 1 + 2 + 4
7 = 1 + 3 + 3
7 = 2 + 2 + 3
7 = 1 + 6
7 = 2 + 5
7 = 3 + 4
bool first = true;
void printNum(ElemType e)
{
if (first) {
printf("%d ", e);
first = false;
} else {
printf("+ %d ", e);
}
}
// 把num分解为n个正整数相加
void decompose(size_t num, size_t orinum, size_t n, ST st)
{
int top = 0;
if (n == 1) {
peek_stack(st, &top);
if (num >= top) {
push_stack(st, num);
first = true;
printf("%d = ", orinum);
foreach_stack(st, printNum);
pop_stack(st, NULL);
printf("\n");
}
return;
}
size_t beg = 1;
if (peek_stack(st, &top) == SUCCESS) {
beg = top;
}
for (; beg < num; ++beg) { // num分解成n>1分。 不直接分 写割除beg 剩下的num-beg分成n - 1份
push_stack(st, beg);
decompose(num - beg, orinum, n - 1, st);
pop_stack(st, NULL);
}
}
判断是一个序列是否可以作为另一个入栈序列的出栈顺序
- 判断是一个序列是否可以作为另一个入栈序列的出栈顺序
入栈序列 1 2 3 4 5
问 1 2 3 4 5 可以是入栈顺序的出栈序列
5 4 3 2 1
1 2 3 5 3
3 1 4 2 5 不可以
book is_stack_out_sqe(int inp[], int out[], size_t n);
bool is_stack_out(int in[], int out[], size_t n)
{
ST st = create_stack(n); // create_stack(sizeof(ElemType));
int j = 0;
for (int i = 0; i < n; ++i) {
push_stack(st, in[i]);
int elem;
while (peek_stack(st, &elem) == SUCCESS && elem == out[j]) { // 如果栈顶 == out[j]
pop_stack(st, NULL);
++j;
}
}
bool ret = empty_stack(st);
destroy_stack(st);
return ret;
}
链栈实现
结构体定义
struct _SNode {
struct _SNode *next;
char elem[];
};
#define _SNODESIZE sizeof(struct _SNode)
struct Stack {
size_t elemSize; // 元素字节大小
size_t size; // 元素个数
struct _SNode *top; // 指向栈顶
};
typedef struct Stack* ST;
基础函数声明
// 创建栈
ST create_stack(size_t elemSize);
// 清空栈
void clear_stack(ST st);
// 销毁
void destroy_stack(ST st);
// 栈中元素个数
size_t size_stack(ST st);
// 栈是否为空
bool empty_stack(ST st);
// 压入栈
int push_stack(ST st, const void *pElem);
// 弹出栈
int pop_stack(ST st, void *pElem);
// 取栈顶
int peek_stack(ST st, void *pElem);
// 迭代
void foreach_stack(ST st, void (*foreach)(const void*));
基础函数实现
创建栈 create_stack
ST create_stack(size_t elemSize) // 传入元素字节大小
{
ST st = (ST)malloc(sizeof(struct Stack)); // 创建一个空栈
if (st != NULL) {
st->elemSize = elemSize;
st->size = 0;
st->top = NULL; // 空栈
}
return st;
}
清空栈 clear_stack
void clear_stack(ST st) // 也可以for循环一个一个释放
{
assert(st != NULL);
while (!empty_stack(st)) {
pop_stack(st, NULL);
}
}
销毁 destroy_stack
void destroy_stack(ST st)
{
assert(st != NULL);
clear_stack(st);
free(st); // 释放栈
}
栈中元素个数 size_stack
size_t size_stack(ST st)
{
assert(st != NULL);
return st->size;
}
栈是否为空 empty_stack
bool empty_stack(ST st)
{
assert(st != NULL);
return st->top == NULL; // st->size == 0;
}
压入栈 push_stack
int push_stack(ST st, const void *pElem)
{
assert(st != NULL && pElem != NULL);
struct _SNode *node = (struct _SNode*)malloc(_SNODESIZE + st->elemSize); // 创建一个栈结点
if (node == NULL) {
return FAILURE;
}
node->next = st->top; // 压入到栈顶
st->top = node;
memcpy(node->elem, pElem, st->elemSize); // 拷贝数据
++st->size;
return SUCCESS;
}
弹出栈 pop_stack
int pop_stack(ST st, void *pElem)
{
assert(st != NULL);
if (empty_stack(st)) {
return FAILURE;
}
struct _SNode *node = st->top;
st->top = node->next; // 从栈顶弹出
if (pElem != NULL) { // 是否返回删除的元素
memcpy(pElem, node->elem, st->elemSize);
}
free(node);
--st->size;
return SUCCESS;
}
取栈顶 peek_stack
int peek_stack(ST st, void *pElem)
{
assert(st != NULL && pElem != NULL);
if (empty_stack(st)) {
return FAILURE;
}
memcpy(pElem, st->top->elem, st->elemSize); // 获取栈顶元素
return SUCCESS;
}
迭代 foreach_stack
void foreach_stack(ST st, void (*foreach)(const void*))
{
assert(st != NULL && foreach != NULL);
struct _SNode *node = st->top;
for (; node != NULL; node = node->next) {
foreach(node->elem);
}
}