栈
1栈基本操作
//结构体定义
typedef struct {
int top;
char data[MaxSize]
} Stack;
//初始化
void InitStack(Stack *s) {
memset(s->data, '.', sizeof(char) * MaxSize);
s->top = -1;
}
//判空
_Bool isEmpty(Stack *s) {
return s->top == MaxSize;
}
//判满
_Bool isFull(Stack *s){
return s->top == MaxSize - 1;
}
//入栈
void Push(Stack *s, char element) {
if (s->top != (MaxSize - 1))
s->data[++s->top] = element;
}
//出栈
void Pop(Stack *s) {
if (s->top != -1)
s->top--;
}
//读取栈顶元素
char getTop(Stack *s) {
char topElement = s->data[s->top];
return topElement;
}
2 利用栈判断回文
//有一段字符串使用字符数组存储,使用栈判断该字符串是否是回文
_Bool IsPalindrome(char *str, int len) {
Stack *s = (Stack *) malloc(sizeof(Stack));
InitStack(s);
int IsOdd = len % 2 ? 1 : 0;
int index = 0;
while (index < len)
if (index < len / 2) {
Push(s, str[index]);
index++;
} else if (index == len / 2 && IsOdd) //字符串长度为奇数,从中间位置的后一位开始比较
index++;
else { //回文比较
if (str[index] == getTop(s)) { //当前字符与栈顶元素相匹配
Pop(s);
index++;
} else return 0;
}
return 1;
}
3 括号匹配
//判断一个算数表达式的括号(包含 "()、[]、{}")是否匹配正确
_Bool IsCorrectMatch(const char *str) {
Stack *s = (Stack *) malloc(sizeof(Stack));
InitStack(s);
while (*str != '\0') {
if (*str == '(' || *str == '[' || *str == '{')
Push(s, *str);
if (*str == ')' || *str == ']' || *str == '}') {
if ((*str == ')' && getTop(s) == '('))
Pop(s);
else if ((*str == ']' && getTop(s) == '['))
Pop(s);
else if ((*str == '}' && getTop(s) == '{'))
Pop(s);
else
return 0;
}
str++;
}
return 1;
}
4 设计共享栈
//使用一个顺序表来设计两个栈 s1 和 s2 的相关操作,type 为 'l' 表示左栈 s1,为 'r' 表示右栈 s2
typedef struct {
int data[MaxSize];
int topL;
int topR;
} ToStack;
//初始化
void ToInitStack(ToStack *s) {
memset(s->data, 0, sizeof(int) * MaxSize);
s->topL = -1;
s->topR = MaxSize;
}
//判空
_Bool ToIsEmpty(ToStack *s, char type) {
if ((type == 'l' && s->topL == -1) || (type == 'r' && s->topR == MaxSize))
return 1;
else
return 0;
}
//判满
_Bool ToIsFull(ToStack *s) {
if (s->topR - s->topL > 1)
return 0;
else
return 1;
}
//入栈
void ToPush(ToStack *s, char type, int val) {
if (!ToIsFull(s)) { //栈不满则入栈
if (type == 'l')
s->data[++s->topL] = val;
else
s->data[--s->topR] = val;
} else
printf("STACK OVERFLOW !");
}
//出栈
void ToPop(ToStack *s, char type) {
if (type == 'l') {
if (!ToIsEmpty(s, type)) {
s->data[s->topL] = 0;
s->topL--;
} else
printf("STACK IS EMPTY !");
} else {
if (!ToIsEmpty(s, type)) {
s->data[s->topR] = 0;
s->topR++;
} else
printf("STACK IS EMPTY !");
}
}
//读取栈顶元素
int ToGetTop(ToStack *s, char type) {
if (type == 'l')
return s->data[s->topL];
else
return s->data[s->topR];
}
5 栈模拟队列
//使用两个栈来模拟一个队列,实现队列的入列、出列、判空操作
typedef struct {
struct Stack *s1;
struct Stack *s2;
} Queue;
void InitQueue(Queue *q) {
memset(q->s1.data, 0, sizeof(int) * MaxSize);
q->s1.top = -1;
memset(q->s2.data, 0, sizeof(int) * MaxSize);
q->s2.top = -1;
}
_Bool QueueEmpty(Queue *q) {
if (q->s1->top == -1 && q->s2->top == -1)
return 1;
else
return 0;
}
void JoinQueue(Queue *q, char val) {
if (!isEmpty(q->s1))
Push(q->s1, val);
}
void LeaveQueue(Queue *q) {
while (q->s1.top != -1) { //s1 中元素转移到 s2,然后出栈来模拟出队列
Push(q->s2, q->s1->data[cur]);
q->s1.top--;
}
Pop(q->s2);
}
6 操作序列是否合法
//假设入栈和出栈分别用 I 和 O 表示,判断操作序列是否合法
_Bool IsItLegal(char *str) {
int count = -1;
while (*str != '\0'){
if (*str == 'I'){
if (count < MaxSize - 1)
count++;
else return 0;
} else if (*str == 'O'){
if (count > -1)
count--;
else return 0;
}
str++;
}
return 1;
}
7 进制转换
//利用栈的思想,将一个非负十进制正整数转化为二进制
void DecimalToBinary(int val) {
Stack *s = (Stack*)malloc(sizeof(Stack));
InitStack(s);
do {
Push(s, val%2);
val /= 2;
}while (val);
while (s->top != -1){
printf("%d", getTop(s));
Pop(s);
}
}
8 栈存储数据
//设读入一整数的序列:a1, a2, a3,…,an,试编写算法实现:用栈结构存储输入的整数,当 ai != -1 时
//将 ai 进栈;当 ai == -1 时,输出栈顶整数并出栈。算法应对异常情况(入栈满等)给出相应的信息
void SaveData(Stack *s, int *val, int len) {
for (int i = 0; i < len; ++i) {
if (val[i] != -1){
if (!isFull(s)){
Push(s, val[i]);
printf("Not meet -1, Push %d\n", val[i]);
} else{
printf("STACK OVERFLOW !");
return;
}
} else{
if (!isEmpty(s)){
printf("Meet -1, Pop %d\n", getTop(s));
Pop(s);
} else{
printf("STACK EMPTY !");
return;
}
}
}
}
9 中缀转逆波兰
//将所给的中缀算术表达式转换成对应的后缀表达式(逆波兰表达式)
void SuffixExpression(Stack *s, char *str) {
while (*str != '\0'){
switch (*str) {
// + 和 - 的优先级低于 * 和 /,依次从栈顶弹出比 + 和 - 优先级高的和相等的运算符
//直至遇到一个优先级比他低的或者左括号为止
case '+':
while (s->top != -1){
if (getTop(s) == '*' || getTop(s) == '/' || getTop(s) == '-') {
printf("%c", getTop(s));
Pop(s);
}
if (getTop(s) == '(') //遇到左括号,终止出栈
break;
}
//比他优先级高或相等的出栈结束,它入栈
Push(s, *str);
break;
case '-':
while (s->top != -1){
if (getTop(s) == '*' || getTop(s) == '/' || getTop(s) == '+') {
printf("%c", getTop(s));
Pop(s);
}
if (getTop(s) == '(') //遇到左括号,终止出栈
break;
}
//比他优先级高或相等的出栈结束,它入栈
Push(s, *str);
break;
case '*': //当前元素为 * 或 /,有优先级最高,直接入栈
Push(s, *str);
break;
case '/':
Push(s, *str);
break;
case '(': //当前为左括号,入栈
Push(s, *str);
break;
case ')': //当前为右括号
while (s->data[s->top] != '('){ //依次将栈中元素输出,直至出现 '('
printf("%c", getTop(s));
Pop(s);
}
//删除 '('
Pop(s);
break;
default: //其余情况下,为表达式中的常量,直接输出
printf("%c", *str);
}
str++;
}
//将栈中的剩余元素依次出栈
while (s->top != -1){
printf("%c", getTop(s));
Pop(s);
}
}
队列
1 队列基本操作
//循环队列结构体
typedef struct {
int data[MaxSize];
int front;
int rear;
}Queue;
//初始化
void Init(Queue *q){
memset(q->data, 0, sizeof(int) * MaxSize);
q->front = q->rear = 0;
}
判空
_Bool IsEmpty(Queue *q){
return q->rear == q->front;
}
//判满
_Bool IsFull(Queue *q){
return (q->rear + 1) % MaxSize == q->front;
}
//入队(队头入队)
void JoinQueue(Queue *q, int val){
if (!IsFull(q)){
q->data[q->rear] = val;
q->rear = (q->rear + 1) % MaxSize;
} else{
printf("QUEUE OVERFLOW !");
return;
}
}
//出队(队尾离队)
void LeaveQueue(Queue *q){
if (!IsEmpty(q)){
q->data[q->front] = 0;
q->front = (q->front + 1) % MaxSize;
} else{
printf("QUEUE EMPTY !");
return;
}
}
//获取队尾元素
int GetRear(Queue *q){
if (!IsEmpty(q))
return q->data[q->rear-1];
else return -1;
}
//循环队列的其他操作与顺序表类似,链队的操作与单链表类似,这里省略