一,顺序栈的静态分配
二,顺序栈的动态分配
2.1结构体
typedef struct Sqstack{
int *base;
int *top;
int stacksize;
}Sqstack;
2.2初始化
void InitStack(Sqstack *s){
(*s).base=(int *)malloc(initsize*sizeof(int));
if(!(*s).base)exit(0);
(*s).top=(*s).base;
(*s).stacksize=initsize;
}
2.3入栈
void Push(Sqstack *s,int e){
if((*s).top-(*s).base >= (*s).stacksize){
(*s).base=(int*)realloc((*s).base,((*s).stacksize+incresize)*sizeof(int));
if(!(*s).base)exit(0);
(*s).top=(*s).base+(*s).stacksize;
(*s).stacksize+=incresize;
}
*((*s).top)=e;
(*s).top++;
}
2.4出栈
void Pop(Sqstack *s,int *e){
if((*s).top==(*s).base) exit(0);
(*s).top--;
*e=*((*s).top);
}
2.5销毁栈
void Destroystack(Sqstack *s){
if(s!=NULL){
free((*s).base);
(*s).base=NULL; (*s).top=NULL;
(*s).stacksize=0;
}
}
2.6栈判空
int StackEmpty(Sqstack s){
return (s.top==s.base);
}
2.7求栈长
int StackLength(Sqstack s){
return s.top-s.base;
}
2.8 主函数
#include<stdio.h>
#include<stdlib.h>
#define initsize 5
#define incresize 5
int main(){
Sqstack s;
InitStack(&s);
int e,p,x;
for(int j=0;j<s.stacksize;j++){
scanf("%d",&e);
Push(&s,e);
}
GetTop(s,&p);
printf("栈顶元素是%d ",p);
if(StackEmpty(s)) printf("\n非空!");
else ("\n empty!");
int length=StackLength(s);
printf("\n 栈长为%d",length);
Pop(&s,&x);
printf("\n 出栈元素是 %d",x);
Destroystack(&s);
return 0;
}
三,栈链
#include<stdio.h>
#include<stdlib.h>
typedef struct stacknode{
int data;
struct stacknode *next;
}stackNode,*Linkstack;
void Initstack(Linkstack *s){
*s=(Linkstack)malloc(sizeof(stackNode));
(*s)->next=NULL;
}
void Push(Linkstack s,int x){
Linkstack p=(Linkstack)malloc(sizeof(stackNode));
if(!p)exit(0);
p->data=x;
p->next=s->next;
s->next=p;
}
void Gettop(Linkstack s,int *e){
if(s->next==NULL)exit(0);
*e=s->next->data;
}
int Empty(Linkstack s){
return (s->next==NULL);
}
void Pop(Linkstack s,int *e){
if(s->next==NULL){
printf("空!");exit(0);
}
stackNode *p=s->next;
e=p->data;
s->next=p->next;
free(p);
}
void Destroystack(Linkstack s){
Linkstack p=s->next,q;
while(p!=NULL){
q=p->next;
free(p);
p=q;
}
free(s);
}
int main(){
Linkstack s;
Initstack(&s);
int n,x;scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
Push(&s,x);
}
Gettop(&s,&x);
printf("栈顶元素是 %d\n",x);
int flag=Empty(s);
if(flag==0)printf("空!");
else printf("非空!");
Pop(&s,&x);
printf("出栈元素是 %d",x);
Destroystack(&s);
return 0;
}
四,进制转换
五,表达式求值
六,括号的匹配问题
七,迷宫问题
八,中缀表达式求值
题目描述
编写一个算法,利用栈求解中缀算术表达式的值。运算符包括+、-、*、/、(、)和=,参加运算的数为个位数整数类型且为正数。(要求:直接针对中缀算术表达式进行计算,不能转换为后缀或前缀表达式再进行计算,只考虑二元运算即可。)
输入
输入一个需要计算的算术表达式,例如:2+2=。
输出
输出为表达式的运算结果。
样例输入 Copy
1+1=
样例输出 Copy
2
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
typedef struct {
Node *top;
} Stack;
int is_operator(char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}
int priority(char op) {
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
int calculate(int a, char op, int b) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default:
exit(1);
}
}
Stack *create_stack() { // 创建空栈
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->top = NULL;
return stack;
}
void push(Stack *stack, int data) { // 入栈操作
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = stack->top;
stack->top = node;
}
int pop(Stack *stack) { // 出栈操作
if (stack->top == NULL) {
return -1; // 如果栈为空,则返回-1
}
Node *node = stack->top;
int data = node->data;
stack->top = node->next;
free(node);
return data;
}
int top(Stack *stack) { // 返回栈顶元素
if (stack->top == NULL) {
return -1; // 如果栈为空,则返回-1
}
return stack->top->data;
}
int evaluate_expression(char *expression) {
Stack *s1 = create_stack(); // 操作数栈,用于存储操作数
Stack *s2 = create_stack(); // 操作符栈,用于存储操作符
for (int i = 0; expression[i] != '='; i++) {
if (is_operator(expression[i])) { // 如果当前字符为操作符
while (s2->top != NULL && priority(top(s2)) >= priority(expression[i])) {
// 如果操作符栈不为空,并且栈顶操作符的优先级大于等于当前操作符的优先级
int b = pop(s1); // 出栈一个操作数作为运算的右操作数
int a = pop(s1); // 再出栈一个操作数作为运算的左操作数
char op = pop(s2); // 出栈一个操作符
int result = calculate(a, op, b); // 计算两个操作数和操作符的结果
push(s1, result); // 将计算结果入栈到操作数栈中
}
push(s2, expression[i]); // 当前操作符入栈到操作符栈中
} else if (expression[i] == '(') { // 如果当前字符为左括号
push(s2, expression[i]); // 入栈到操作符栈中
} else if (expression[i] == ')') { // 如果当前字符为右括号
while (top(s2) != '(') { // 循环执行直到遇到左括号
int b = pop(s1); // 出栈一个操作数作为运算的右操作数
int a = pop(s1); // 再出栈一个操作数作为运算的左操作数
char op = pop(s2); // 出栈一个操作符
int result = calculate(a, op, b); // 计算两个操作数和操作符的结果
push(s1, result); // 将计算结果入栈到操作数栈中
}
pop(s2); // 弹出左括号
} else { // 如果当前字符为数字
int num = expression[i] - '0'; // 将当前字符转换成数字
while (expression[i + 1] >= '0' && expression[i + 1] <= '9') {
// 如果下一个字符也是数字,则将其合并到一起
num = num * 10 + expression[++i] - '0';
}
push(s1, num); // 将数字入栈到操作数栈中
}
}
// 处理剩余的操作符
while (s2->top != NULL) {
int b = pop(s1); // 出栈一个操作数作为运算的右操作数
int a = pop(s1); // 再出栈一个操作数作为运算的左操作数
char op = pop(s2); // 出栈一个操作符
int result = calculate(a, op, b); // 计算两个操作数和操作符的结果
push(s1, result); // 将计算结果入栈到操作数栈中
}
return pop(s1); // 返回最终的计算结果
}
int main() {
char expression[100];
scanf("%s", expression);
int result = evaluate_expression(expression);
printf("%d\n", result);
return 0;
}
wenti:
#include<stdio.h>
#include<stdlib.h>
typedef struct stacknode{
int data;
struct stacknode *next;
}StackNode,*StackLink;
StackLink *Initstack(){
StackLink s;
s=(StackLink)malloc(sizeof(StackNode));
s->next=NULL;
return s;
}
void Push(StackLink stack,int e){
StackNode *node=(StackNode *)malloc(sizeof(StackNode));
//if(!node)exit(0);
node->data=e;
node->next=stack->next;
stack->next=node;
}
int Pop(StackLink stack,int *e){
if(stack->next ==NULL)return 0;
StackLink p=stack->next;
* e=p->data;
stack->next=p->next;
free(p);
return 1;
}
int GetTop(StackLink stack,int *e){
if(stack->next==NULL){
return -1;
}
*e=stack->next->data;
return 0;
}
int is_operator(char x){
if(x=='+'||x=='-'||x=='*'||x=='/'){
return 1;
}
return 0;
}
int prio(char ope){
switch(ope){
case'+':
case'-':
return 1;
case'*':
case'/':
return 2;
default:
return 0;
}
}
int calculate(int a,char op,int b){
switch(op){
case'+':return a+b;
case'-':return a-b;
case'*':return a*b;
case'/':return a/b;
default:exit(0);
}
}
int Get_evaluate(char exp[1000]){
StackLink s1,s2;
s1=Initstack();
s2=Initstack();
for(int i=0;exp[i]!='=';i++){
if(is_operator(exp[i])==1){//运算符
if(s2->next !=NULL && prio(s2->next)>=prio(exp[i])){
int b;Pop(s1,&b);
int a;Pop(s2,&a);
char op;Pop(s1,&op);
int result =calculate(a,op,b);
Push(s1,result);
}
}
else if(exp[i]=='('){
Push(s2,exp[i]);
}
else if(exp[i]==')'){
while(s2->data!='('){
int b;Pop(s1,&b);
int a;Pop(s2,&a);
char op;Pop(s1,&op);
int result =calculate(a,op,b);
Push(s1,result);
}
int a;Pop(s2,a);//a存放s2出栈数字
}
else{//数字
int num=exp[i]-'0';
while(exp[i+1]>='0'&&exp[i+1]<='9'){
num=num*10+exp[++i]-'0';
}
Push(s1,num);
}
}
// 处理剩余的操作符
while (s2->next != NULL) {
int b;Pop(s1,&b);
int a;Pop(s2,&a);
char op;Pop(s1,&op);
int result =calculate(a,op,b);
Push(s1,result);
}
int t;Pop(s1,&t); // 返回最终的计算结果
return t;
}
int main(){
char exp[1000];
scanf("%s",exp);
int result =Get_evaluate(exp);
printf("%d",result);
return 0;
}
九,双向栈的基本操作
题目描述
将编号为0和1的两个栈存放于一个数组空间V[m]中,栈底分别处于数组的两端。当第0号栈的栈顶指针top[0]等于-1时该栈为空;当第1号栈的栈顶指针top[1]等于m时,该栈为空。两个栈均从两端向中间增长。试编写双栈初始化,判断栈空、栈满、进栈和出栈算法的函数。函数调用次序依次为:进栈、栈满的判断、出栈、栈空的判断。
输入
第一行为一个整数m,表示数组V的大小,
第二行为四个整数e0、e1、d0、d1,e0和e1分别代表压入0号栈和1号栈的整数序列E0和E1的长度(依次连续入栈,中间没有出栈的情况),d0和d1分别代表从0号栈和1号栈弹出的序列的长度(依次连续出栈,中间没有入栈的情况)。
第三行和第四行分别表示序列E0和E1。
输出
第一行代表进栈操作完成时栈是否为满(出栈操作尚未执行),栈满输出1,栈不满输出0。
第二行对应0号栈,第二行包括d0+1个整数,其中前d0个整数代表出栈序列D0,最后一个整数代表出栈操作完成时0号栈是否为空,栈空输出0,不空输出1。
第三行对应1号栈,第三行包括d1+1个整数,其中前d1个整数代表出栈序列D1,最后一个整数代表出栈操作完成时1号栈是否为空,栈空输出0,不空输出1。整数之间用空格分隔。
样例输入 Copy
7
3 4 2 2
1 2 3
2 3 4 5
样例输出 Copy
1
3 2 1
5 4 1
#include <stdio.h>
#include <stdlib.h>
typedef int elem;
typedef struct
{
int top[2];//定义栈顶和栈底指针 int bot[2];
int *V; //栈数组
int m; //栈最大可容纳元素个数
}DblStack;
//初始化双栈
void InitDblStack(DblStack *stack,int x)
{
int *arr = (elem*)malloc(x*sizeof(elem));//申请空间
stack->V = arr; //将V指针指向申请的空间
stack->m = x; //初始化栈最大可容纳最大元素个数
stack->top[0] = -1; //左栈栈顶指针初始化
stack->top[1] = stack->m; //右栈栈顶指针初始化
//stack->bot[0] = 0; //左栈栈底指针初始化
//stack->bot[1] = stack->m-1; //右栈栈底指针初始化
}
//判断总体是否为空栈
int EmptyDblStack(DblStack stack)
{
if(stack.top[0] == -1 && stack.top[1] == stack.m)
return 1; //若是返回1
return 0; //否则返回0
}
//判断左栈是否为空栈
int EmptyLeft(DblStack stack)
{
if(stack.top[0] == -1)
return 0; //若是返回1
return 1; //否则返回0
}
//判断右栈是否为空栈
int EmptyRight(DblStack stack)
{
if(stack.top[1] == stack.m )//加&& stack.top[0]==-1
return 0; //若是返回1
return 1; //否则返回0
}
//判断是否为满栈
int FullDblStack(DblStack stack)
{
if(stack.top[1] - stack.top[0]==1 || stack.top[0] >= stack.m || stack.top[1] < 0 )
//三种满栈情况左右两栈中间相遇,左栈满,右栈满
return 1;//满栈返回1
return 0;//否则返回0
}
int Fullleft(DblStack stack){
if(stack.top[0] >= stack.m )return 1;
else return 0;
}
int Fullright(DblStack stack){
if(stack.top[1] <0 )return 1;
else return 0;
}
//左栈进栈
int pushLeft(DblStack *stack, elem e)
{
if (stack->top[1] - stack->top[0] ==1)//判断是否为满栈
{
printf("栈已满不能进行进栈操作\n");
return 0; //满栈返回0
}
stack->top[0]++; //左栈栈顶指针加一
stack->V[stack->top[0]] = e; //将数据元素进栈
//printf("%d ",stack->V[stack->top[0]]);
return 1; //完成操作返回1
}
//右栈进栈
int pushRight(DblStack *stack, elem e)
{
if (stack->top[1] - stack->top[0] ==1)//判断是否为满栈
{
printf("栈已满,无法进行进栈操作\n");
return 0; //满栈返回0
}
else{
stack->top[1]--; //右栈栈顶指针加一
stack->V[stack->top[1]] = e; //将数据元素进栈
//printf("%d ",stack->V[stack->top[1]]);
return 1;
}
}
//左栈出栈
elem popLeft(DblStack *stack)
{
if (stack->top[0] == -1)//判断是否为空栈
{
printf("左栈已空,无法进行出栈操作\n");
return 0; //空栈返回0
}
elem e = stack->V[stack->top[0]]; //取出栈顶数据元素
stack->top[0]--; //左栈栈顶元素减一
// stack->V[stack->top[0]];
return e; //返回原栈顶元素
}
//右栈出栈
elem popRight(DblStack *stack)
{
if (stack->top[0] == stack->m) //判断是否为空栈
{
printf("右栈已空,无法进行出栈操作\n");
return 0; //空栈返回0
}
elem e = stack->V[stack->top[1]]; //取出右栈栈顶元素
stack->top[1]++; //右栈栈顶指针加一
return e; //返回原栈顶元素
}
//遍历双栈
void printDblStack(DblStack stack)
{
for (int i = 0; i <= stack.top[0]; i++) //输出左栈
{
printf("%d ", stack.V[i]);
}
printf("\n");
for(int i = stack.top[1]; i < stack.m; i++)//输出右栈
{
printf("%d ", stack.V[i]);
}
printf("\n");
}
//调试
int main()
{
int m,e0,e1,d0,d1;
DblStack stack;
scanf("%d",&m);
InitDblStack(&stack,m); //初始化双栈
scanf("%d %d %d %d",&e0,&e1,&d0,&d1);
for(int j=0;j<e0;j++){//左栈进栈
int E0[e0];
scanf("%d",&E0[j]);
pushLeft(&stack, E0[j]);
}
for(int j=0;j<e1;j++){//右栈进栈
int E1[e1];
scanf("%d",&E1[j]);
pushRight(&stack, E1[j]);
}
// printDblStack(stack);
printf( FullDblStack(stack) ==1?"1":"0");//判断是否为满栈
printf("\n");
for(int j=0;j<d0;j++){
int x=popLeft(&stack);
printf("%d ",x);
}
int x=EmptyLeft(stack);
printf("%d",x);
printf("\n");
for(int j=0;j<d1;j++){
int x=popRight(&stack);
printf("%d ",x);
}
x=EmptyRight(stack);
printf("%d",x);
printf("\n");
// printDblStack(stack);
return 0;
}
十,括号匹配
题目描述
编写一个算法,利用栈检查一个字符数组表示的字符中的花括号、方括号和圆括号是否配对,若能够全部配对则返回1,否则返回0。
输入
输入需要检查的括号字符串,例如:{{([][])}()}。
输出
输出检查结果(全部配对则返回1,否则返回0)。
样例输入 Copy
{{([][])}()}
样例输出 Copy
1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define MaxSize 100 //定义栈中元素最大个数
typedef struct{
char data[MaxSize];
int top;
}SqStack;
//初始化栈
void InitStack(SqStack *S){
S->top = -1;
}
//判断栈是否为空
bool IsEmpty(SqStack S){
if(S.top == -1){
return true;
}
return false;
}
//新元素入栈
void Push(SqStack *S,char x){
if(S->top == MaxSize-1){
printf("栈已满"); //栈已满
return;
}
S->top += 1;
S->data[S->top] = x;
}
//栈顶元素出栈,用x返回
void Pop(SqStack *S,char *x){
if(S->top == -1){
printf("栈已满");
return;
}
*x = S->data[S->top];
S->top -= 1;
}
//匹配算法
bool bracketCheck(char str[],int length){
SqStack S;
InitStack(&S); //初始化栈
for(int i=0;i<length;i++){
if(str[i]=='('||str[i]=='{'||str[i]=='['){
Push(&S,str[i]); //扫描到左括号就入栈
}else{
if(IsEmpty(S)){ //扫描到右括号,当前栈为空,即右括号单身情况
return false; //匹配失败
}
char topElem; //用来保存弹出栈的栈顶元素
Pop(&S,&topElem); //栈顶元素出栈
if(str[i]==')'&&topElem!='('){
return false;
}
if(str[i]=='}'&&topElem!='{'){
return false;
}
if(str[i]==']'&&topElem!='['){
return false;
}
}
}
return IsEmpty(S);
}
int main(){
char s[MaxSize];
scanf("%s",s);
int len = strlen(s);
if(bracketCheck(s,len)){
printf("1");
}else{
printf("0");
}
return 0;
}
十一,进制转换
题目描述
编写一个算法,利用栈将一个非负的十进制整数分别转换为一个二进制数、一个八进制数和一个十六进制数。
输入
输出
第一行输出转换后的二进制元素,例如:1010011010;
第二行输出转换后的八进制元素,例如:1232;
第三行输出转换后的十六进制元素,例如:29A。
样例输入 Copy
666
样例输出 Copy
1010011010
1232
29A
#include <stdlib.h>
#include <stdio.h>
//#ifndef __STACK_H
//#define __STACK_H
#define MaxSize 1000
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];
int top;
}Sqstack;
//创建一个空栈
Sqstack * Stack_Creat(Sqstack * Stack)
{
Stack = (Sqstack *)malloc(sizeof(Sqstack));
if(Stack == NULL)
{
printf("空间已满!\n");
return 0;
}
Stack->top = -1; //空栈
return Stack;
}
//摧毁栈
void Stack_Destory(Sqstack * Stack)
{
free(Stack);
}
//出栈
ElemType Stack_Pop(Sqstack * Stack)
{
ElemType e=-1;
if(Stack->top == -1)
printf("该栈为空栈,无法出栈!\n");
else
{
e = Stack->data[Stack->top];
Stack->top--;
}
return e;
}
//入栈
void Stack_Push(Sqstack * Stack,ElemType e)
{
if(Stack->top == MaxSize - 1)
{
printf("栈已满,无法入栈!\n");
}
else
{
Stack->top++;
Stack->data[Stack->top] = e;
}
}
//判断栈是否为空
int Stack_Empty(Sqstack * Stack)
{
return (Stack->top == -1 );
}
void DTB(int num,Sqstack * Stack)
{
char num_b[33] ; //用来存放转换出来的二进制
char * temp = num_b;
while(num) //入栈
{
Stack_Push(Stack,num%2);
num /= 2;
}
while(!Stack_Empty(Stack))//出栈 直到栈为空
{
*temp = Stack_Pop(Stack) + '0';
temp++;
}
*temp = '\0';
printf("%s\n",num_b);
}
void DTO(int num,Sqstack * Stack)
{
char num_o[12] ; //用来存放转换出来的二进制
char * temp = num_o;
while(num) //入栈
{
Stack_Push(Stack,num%8);
num /= 8;
}
while(!Stack_Empty(Stack))//出栈 直到栈为空
{
*temp = Stack_Pop(Stack) + '0';
temp++;
}
*temp = '\0';
printf("%s\n",num_o);
}
void DTH(int num,Sqstack * Stack)
{
char num_h[12] ; //用来存放转换出来的二进制
char * temp = num_h;
int top_num;
while(num) //入栈
{
Stack_Push(Stack,num%16);
num /= 16;
}
while(!Stack_Empty(Stack))//出栈 直到栈为空
{
top_num = Stack_Pop(Stack);
if(top_num>9)
*temp = top_num - 10 + 'A';
else
*temp = top_num + '0';
temp++;
}
*temp = '\0';
printf("%s\n",num_h);
}
int main(){
int flag=1,a,num_d;
Sqstack * Stack;
Stack = Stack_Creat(Stack);
scanf("%d",&num_d);
if(num_d>0){
DTB(num_d,Stack);
DTO(num_d,Stack);
DTH(num_d,Stack);
}
if(num_d==0){
printf("0 \n0 \n0 \n");
}
return 0;
}
十二,入栈出栈基本操作
题目描述
输入一个整数序列a1,a2,a3...,an。当ai不等于-1时将ai进栈;当ai=-1时,输出栈顶元素并将其出栈。
输入
第一行为序列的长度n,
第二行为n个整数,整数之间用空格分隔。
输出
样例输入 Copy
5
1 2 -1 -1 1
样例输出 Copy
2
1
#include<stdio.h>
#include<stdlib.h>
//#define initsize 5
#define incresize 5
typedef struct Sqstack{
int *base;
int *top;
int stacksize;
}Sqstack;
void InitStack(Sqstack *s,int initsize){
(*s).base=(int *)malloc(initsize*sizeof(int));
if(!(*s).base)exit(0);
(*s).top=(*s).base;
(*s).stacksize=initsize;
}
void Push(Sqstack *s,int e){
if((*s).top-(*s).base >= (*s).stacksize){
(*s).base=(int*)realloc((*s).base,((*s).stacksize+incresize)*sizeof(int));
if(!(*s).base)exit(0);
(*s).top=(*s).base+(*s).stacksize;
(*s).stacksize+=incresize;
}
*((*s).top)=e;
(*s).top++;
}
void GetTop(Sqstack s,int *e){
if(s.top==s.base) printf("empty!");
*e=*(s.top-1);
}
int StackLength(Sqstack s){
return s.top-s.base;
}
int StackEmpty(Sqstack s){
if(s.top==s.base)return 0;
else return 1;
}
void Pop(Sqstack *s,int *e){
if((*s).top==(*s).base) exit(0);
(*s).top--;
*e=*((*s).top);
}
void Destroystack(Sqstack *s){
if(s!=NULL){
free((*s).base);
(*s).base=NULL; (*s).top=NULL;
(*s).stacksize=0;
}
}
int main(){
Sqstack s;
int n;
scanf("%d",&n);
InitStack(&s,n);
int e,p,x;
s.stacksize=n;
for(int j=0;j<s.stacksize;j++){
scanf("%d",&e);
if(e!=-1){
Push(&s,e);
}
else{
if(StackEmpty(s)==0) //printf("\n非空!");
{
printf("出栈失败");
exit(0);
}
GetTop(s,&p);
printf("%d\n",p);
Pop(&s,&x);
//printf("%d",x);
}
}
return 0;
}