栈
栈:结构定义
放入元素是从底向上放入
 有一个栈顶指针,永远处在栈顶的元素
 还需要标记栈大小的size
 栈的性质: Fisrt-in Last-out (FILO) 先进后出
 栈改变元素的顺序

栈:出栈
让栈顶指针向下移动一位
 
栈:入栈
栈顶指针向上移动一位,然后把元素放进来
 
栈:数组实现
结构定义
typedef struct Stack{
	int *data;
	int size, top;
} Stack;
初始化栈
 top指针一开始指向-1
Stack *initStack(int n)
{
	Stack *s = (Stack*)malloc(sizeof(Stack));
	s->data = (int *)malloc(sizeof(int)* n);
	s->size = n;
	s->top = -1;
	return s;
}
栈判空
// 栈判空
int empty(Stack *s)
{
	return s->top == -1;
}
查看栈顶元素
// 查看栈顶元素
int top(Stack *s)
{
	if (empty(s)) return 0;
	return s->data[s->top]; 
}
入栈
// 入栈
int push(Stack *s, int val)
{
	if (s->top + 1 == s->size) return 0;  // 栈是否满了
	s->top += 1;
	s->data[s->top] = val;
	return 1;
}
出栈
// 出栈
int pop(Stack *s)
{
	if (empty(s)) return 0;
	s->top -= 1;
	return 1;
}
销毁栈
// 销毁栈
void clearStack(Stack *s)
{
	if (s == NULL) return;
	free(s->data);
	free(s);
	return;
}
栈:代码演示
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
typedef struct Stack{
	int *data;
	int size, top;
} Stack;
Stack *initStack(int n)
{
	Stack *s = (Stack*)malloc(sizeof(Stack));
	s->data = (int *)malloc(sizeof(int)* n);
	s->size = n;
	s->top = -1;
	return s;
}
// 栈判空
int empty(Stack *s)
{
	return s->top == -1;
}
// 查看栈顶元素
int top(Stack *s)
{
	if (empty(s)) return 0;
	return s->data[s->top]; 
}
// 入栈
int push(Stack *s, int val)
{
	if (s->top + 1 == s->size) return 0;  // 栈是否满了
	s->top += 1;
	s->data[s->top] = val;
	return 1;
}
// 出栈
int pop(Stack *s)
{
	if (empty(s)) return 0;
	s->top -= 1;
	return 1;
}
// 销毁栈
void clearStack(Stack *s)
{
	if (s == NULL) return;
	free(s->data);
	free(s);
	return;
}
// 输出栈
void outputStack(Stack *s)
{
	printf("Stack:  ");
	for (int i = s->top; i >= 0; --i)
	{
		printf("%4d", s->data[i]);
	}
	printf("\n\n");
	return;
}
int main()
{
	srand(time(0));
    #define MAX_OP 10
	Stack *s = initStack(MAX_OP);
	for (int i = 0; i < MAX_OP; i++)
	{
		int op = rand() % 3, val = rand() % 100;    // 0: pop;  1, 2: push
		switch (op)
		{
		case 0:
			printf("pop stack, item = %d\n", top(s));
			pop(s);
			break;
		case 1:
		case 2:
			printf("push stack, item = %d\n", val);
			push(s, val);
			break;
		}
		outputStack(s);
	}
	clearStack(s);
	std::cin.get();
	return 0;
}
测试结果

Leetcode-20. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
 输出:true
示例 2:
输入:s = “()[]{}”
 输出:true
示例 3:
输入:s = “(]”
 输出:false
提示:
1 <= s.length <= 104
 s 仅由括号 ‘()[]{}’ 组成
题目解析
怎么判断一个括号序列满足相互包含的相互关系?

 一开始,top指针指向-1
 
 碰到左括号"(“,入栈
 
 遇到左括号”{“,继续入栈
 
 遇到右括号,且匹配得上栈顶元素,出栈
 
 遇到右括号,且匹配得上栈顶元素,继续出栈
 
 遇到左括号“[”,入栈
 
 遇到左括号”(“,继续入栈
 
 遇到右括号,且与栈顶元素匹配,出栈
 
 遇到左括号”{",入栈
 
 遇到右括号,且与栈顶元素匹配,出栈
 
遇到右括号,且与栈顶元素匹配,出栈
 
最后,栈为空,判定括号序列合法
代码演示
先改写栈的代码,将其从int类型全部改为char类型
typedef struct Stack{
	char *data;
	int size, top;
} Stack;
Stack *initStack(int n)
{
	Stack *s = (Stack*)malloc(sizeof(Stack));
	s->data = (char *)malloc(sizeof(char)* n);
	s->size = n;
	s->top = -1;
	return s;
}
// 栈判空
int empty(Stack *s)
{
	return s->top == -1;
}
// 查看栈顶元素
char top(Stack *s)
{
	if (empty(s)) return 0;
	return s->data[s->top];
}
// 入栈
int push(Stack *s, char val)
{
	if (s->top + 1 == s->size) return 0;  // 栈是否满了
	s->top += 1;
	s->data[s->top] = val;
	return 1;
}
// 出栈
int pop(Stack *s)
{
	if (empty(s)) return 0;
	s->top -= 1;
	return 1;
}
// 销毁栈
void clearStack(Stack *s)
{
	if (s == NULL) return;
	free(s->data);
	free(s);
	return;
}
主程序代码
void solve(char str[])
{
	int flag = 1;    // 是否匹配成功
	Stack *s = initStack(100);
	// 扫描字符串的每一位
	for (int i = 0; str[i]; i++)
	{
		if (str[i] == '(' || str[i] == '[' || str[i] == '{')
		{
			push(s, str[i]);
		}
		else
		{
			// 判断是否与栈顶元素匹配
			switch (str[i])
			{
			case ')':
				if (top(s) == '(') pop(s); 
				else flag = 0;     // 没有匹配成功
				break;
			case ']': 
				if (top(s) == '[') pop(s);
				else flag = 0;   
				break;
			case '}':
				if (top(s) == '{') pop(s);
				else flag = 0;
				break;
			}
			if (flag == 0) break;
		}
		
	}
	if (flag == 0 || !empty(s)) printf("error");
	else printf("success\n");
	clearStack(s);
}
int main()
{
	
	char str[100];
	while (scanf_s("%s", str))
	{
		solve(str);
	}
	
	std::cin.get();
	return 0;
}
输入1:([{}]){{{[]}}}{}
 输出1:success: ([{}]){{{[]}}}{}
输入2: ((((([]{}[]{}
 输出2: error: ((((([]{}[]{}
输入3: (([]{}))))
 输出3: error: (([]{}))))
总结
栈的作用:判断括号序列是否合法
 括号序列本身是一个完全包含关系,栈就是可以处理这种具有完全包含关系的问题。
参考
ACM大牛带你玩转算法与数据结构
Leetcode



















