顺序栈的详解

一、栈的定义

1.1 栈的定义

栈是一种特殊的数据结构,它的特点是后进先出(Last In First Out,LIFO)。栈是一种线性结构,它可以用来存储一组具有相同类型的数据元素。栈的基本操作包括压入(push)和弹出(pop),其中压入操作将数据元素添加到栈的顶部,弹出操作将栈顶的数据元素移除并返回。

1.2 栈的特点

栈的特点包括:

  1. 后进先出:栈中最后一个添加的元素最先被弹出。

  2. 只能在栈顶进行操作:栈的操作只能在栈顶进行,不能在中间或底部操作,因为栈是一种先进后出的结构。

  3. 可以用数组或链表实现:栈可以用数组或链表来实现,数组实现的栈需要指定栈的大小,而链表实现的栈可以动态扩展。

  4. 存储空间受限:栈的存储空间是有限的,一旦达到栈的存储上限,就会出现栈溢出的问题。

  5. 可以用递归实现:栈也可以通过递归的方式来实现,每次递归函数调用都会将参数和返回地址压入栈中,直到递归结束,最后按照相反的顺序弹出栈中的元素。

二、栈的实现使用与应用

2.1 栈的接口定义

typedef int DataType;


typedef struct
{
	DataType *data; /* 堆空间 */
	int maxsize;
	int top;		/* 栈顶指针 */
}SeqStack;


/* 1. 初始化 */
int init(SeqStack *S, int MaxSize);

/* 2. 进(入)栈 */
int push(SeqStack *S, DataType x);

/* 3. 出栈 */
int pop(SeqStack *S, DataType *x);

/* 4. 取栈顶元素 */
int get_top(SeqStack *S, DataType *x);

/* 5. 栈为空?*/
int empty(SeqStack *S);

/* 6. 栈满?*/
int full(SeqStack *S);

/* 7. 销毁*/
int destroy(SeqStack *S);

2.2 栈的实现

2.2.1  栈的初始化
int init(SeqStack *S, int MaxSize)
{
	/*申请内存空间*/
	S->data = (DataType*)malloc(sizeof(DataType)*MaxSize);

	if(!S->data)
	{
		printf("内存申请错误,初始化失败![10001]\n");
		return 10001;
	}
	S->maxsize = MaxSize;
	S->top = -1;
	return 0;
}
2.2.2  入栈
int push(SeqStack *S, DataType x)
{
	/*是否满?*/
	if(full(S))
	{
		printf("栈已满!10002\n");
		return 10002;
	}

	S->top++;			/*移动指针*/
	S->data[S->top] = x;/*放入数据*/
	return 0; /*OK*/
}
2.2.3  出栈
int pop(SeqStack *S, DataType *x)
{
	/*是否空?*/
	if(empty(S))
	{
		printf("栈为空!10003\n");
		return 10003;
	}

	*x = S->data[S->top];	/*栈顶元素赋值给x*/
	S->top--;				/*移动栈顶指针*/	

	return 0;
}
2.2.4  查找栈顶元素
int get_top(SeqStack *S, DataType *x)
{
	/*是否空?*/
	if(empty(S))
	{
		printf("栈为空!10003\n");
		return 10003;
	}

	*x = S->data[S->top];	/*栈顶元素赋值给x*/

	return 0;
}
2.2.5  判断栈是否为空
int empty(SeqStack *S)
{
	return (S->top == -1)?1:0;
}
2.2.6  判断栈是否已满
int full(SeqStack *S)
{
	return (S->top == S->maxsize - 1)?1:0;
}
2.2.7  销毁栈
int destroy(SeqStack *S)
{
	free(S->data);
	return 0;
}

2.3栈的应用

2.3.1十进制转二进制
int d_to_b(int d)
{
	SeqStack S;
	int b;

	/*初始化栈*/
	init(&S,32);

	/*d不为0,余数进栈*/
	while(d)
	{
		push(&S, d % 2);
		d /= 2;
	}
	
	/*依次出栈*/
	while(!empty(&S))
	{
		pop(&S,&b);
		printf("%d", b);
	}

	/*销毁栈*/
	destroy(&S);
}
2.3.2后缀表达式计算
int expression()
{
	SeqStack S;
	int i;
	int op1, op2;	
	int x;

	char exp[20]; /*后缀表达式*/

	init(&S, 10);

	printf("请输入一个后缀表达式(eg. 56+):");
	scanf("%s", exp);
	for(i=0;i<strlen(exp);i++)
	{
		switch(exp[i])
		{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			/*入栈*/
			push(&S, exp[i]-48);
			printf("%c\n",exp[i]);
			break;
		case '+':
			/*出2个*/
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 + op2;
			push(&S, x);
			break;

		case '*':
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 * op2;
			push(&S, x);
			break;
		case '-':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2- op1;
			push(&S, x);
			break;
		case '/':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2/op1;
			push(&S, x);
			break;	
		}
	}
	pop(&S, &x);
	printf("计算结果为:%s = %d\n", exp, x);
	destroy(&S);
}

2.4栈的使用

#include <stdio.h>
#include "seqstack.h"
#include "welcome.h"


int main(int argc, char* argv[])
{
	SeqStack S;
	DataType x;
	int maxsize;
	char yn;
	int i,m,n,cmd,d;
;
	for(i=0;i<strlen(welcome);i++)
	{
		printf("%c",welcome[i]);
		for(m=0;m<1000;m++)
			for(n=0;n<1000;n++)
			{
				;
			}
	}
	
		printf("---------顺序栈演示程序-----------\n");
	do
	{
		printf(" 1. 初始化\n");
		printf(" 2. 入栈\n");
		printf(" 3. 出栈\n");
		printf(" 4. 查找栈顶元素\n");
		printf(" 5. 判断栈为是否空\n");
		printf(" 6. 判断栈为是否满\n"); 
		printf(" 7. 销毁栈\n"); 
		printf(" 8. 栈的应用\n");
		printf(" 9. 帮助\n");
		printf("请选择(0~9,0退出):");
		scanf("%d", &cmd);
		switch(cmd)
		{
		case 1:
			printf("请输入栈的最大存储空间(MaxSize):");
			scanf("%d", &maxsize);
			if(!init(&S, maxsize))
			{
				printf("栈已初始化!\n");
			}
			break;
		case 2:
			printf("请输入入栈元素:x=");
			scanf("%d", &x);
			if(!push(&S, x))
			{
				printf("元素【%d】已入栈!\n", x);

			}
			break;
		case 3:
			printf("确定要出栈(出栈后数据不可恢复,y|n,n)?");
			fflush(stdin);
			scanf("%c", &yn);
			if(yn == 'y' || yn == 'Y')
			{
				if(!pop(&S, &x))
				{
					printf("栈顶元素【%d】已出栈!\n", x);
				}
			}

			break;
		case 4:
			if(!get_top(&S,&x)){
				printf("查找到栈顶元素[%d]\n",x); 
			}
			break; 
		case 5:
			if(empty(&S)){
				printf("栈为空!\n"); 
			}else{
				printf("栈内存在元素\n"); 
			}
			break;
		case 6:
			if(full(&S)){
				printf("栈满!\n"); 
			}else{
				printf("栈未满\n"); 
			}
			break;
		case 7:
			destroy(&S);
			printf("栈已销毁\n"); 	
			break;
		case 8:
			do
			{
				printf("----------8.栈的应用------------\n");
				printf(" 1. 十进制转换为二进制\n");
				printf(" 2. 后缀表达式计算\n");			
				printf(" 0. 返回\n");
				printf("请选择:");
				scanf("%d", &cmd);

				if(cmd == 1)
				{
					printf("请输入一个十进制数:");
					scanf("%d", &d);
					printf("二进制为:");
					d_to_b(d);
					printf("\n");
				}

				if(cmd == 2)
				{
					expression();
				}
			}while(cmd!=0);
			cmd = -1;
			break;
		case 9:
			printf(" 本程序为栈的演示程序,由黄彬森设计开发,程序完成了栈的基本功能!\n");		
		default:
			printf("输入选项不存在\n"); 		
		}

	}while(cmd!=0);

	return 0;
}
/*十进制转换为二进制*/
int d_to_b(int d)
{
	SeqStack S;
	int b;

	/*初始化栈*/
	init(&S,32);

	/*d不为0,余数进栈*/
	while(d)
	{
		push(&S, d % 2);
		d /= 2;
	}
	
	/*依次出栈*/
	while(!empty(&S))
	{
		pop(&S,&b);
		printf("%d", b);
	}

	/*销毁栈*/
	destroy(&S);
}


/*后缀表达式计算*/
int expression()
{
	SeqStack S;
	int i;
	int op1, op2;	
	int x;

	char exp[20]; /*后缀表达式*/

	init(&S, 10);

	printf("请输入一个后缀表达式(eg. 56+):");
	scanf("%s", exp);
	for(i=0;i<strlen(exp);i++)
	{
		switch(exp[i])
		{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			/*入栈*/
			push(&S, exp[i]-48);
			printf("%c\n",exp[i]);
			break;
		case '+':
			/*出2个*/
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 + op2;
			push(&S, x);
			break;

		case '*':
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 * op2;
			push(&S, x);
			break;
		case '-':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2- op1;
			push(&S, x);
			break;
		case '/':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2/op1;
			push(&S, x);
			break;	
		}
	}
	pop(&S, &x);
	printf("计算结果为:%s = %d\n", exp, x);
	destroy(&S);
}

三、完整代码

3.1  main.c文件代码

#include <stdio.h>
#include "seqstack.h"
#include "welcome.h"


int main(int argc, char* argv[])
{
	SeqStack S;
	DataType x;
	int maxsize;
	char yn;
	int i,m,n,cmd,d;
;
	for(i=0;i<strlen(welcome);i++)
	{
		printf("%c",welcome[i]);
		for(m=0;m<1000;m++)
			for(n=0;n<1000;n++)
			{
				;
			}
	}
	
		printf("---------顺序栈演示程序-----------\n");
	do
	{
		printf(" 1. 初始化\n");
		printf(" 2. 入栈\n");
		printf(" 3. 出栈\n");
		printf(" 4. 查找栈顶元素\n");
		printf(" 5. 判断栈为是否空\n");
		printf(" 6. 判断栈为是否满\n"); 
		printf(" 7. 销毁栈\n"); 
		printf(" 8. 栈的应用\n");
		printf(" 9. 帮助\n");
		printf("请选择(0~9,0退出):");
		scanf("%d", &cmd);
		switch(cmd)
		{
		case 1:
			printf("请输入栈的最大存储空间(MaxSize):");
			scanf("%d", &maxsize);
			if(!init(&S, maxsize))
			{
				printf("栈已初始化!\n");
			}
			break;
		case 2:
			printf("请输入入栈元素:x=");
			scanf("%d", &x);
			if(!push(&S, x))
			{
				printf("元素【%d】已入栈!\n", x);

			}
			break;
		case 3:
			printf("确定要出栈(出栈后数据不可恢复,y|n,n)?");
			fflush(stdin);
			scanf("%c", &yn);
			if(yn == 'y' || yn == 'Y')
			{
				if(!pop(&S, &x))
				{
					printf("栈顶元素【%d】已出栈!\n", x);
				}
			}

			break;
		case 4:
			if(!get_top(&S,&x)){
				printf("查找到栈顶元素[%d]\n",x); 
			}
			break; 
		case 5:
			if(empty(&S)){
				printf("栈为空!\n"); 
			}else{
				printf("栈内存在元素\n"); 
			}
			break;
		case 6:
			if(full(&S)){
				printf("栈满!\n"); 
			}else{
				printf("栈未满\n"); 
			}
			break;
		case 7:
			destroy(&S);
			printf("栈已销毁\n"); 	
			break;
		case 8:
			do
			{
				printf("----------8.栈的应用------------\n");
				printf(" 1. 十进制转换为二进制\n");
				printf(" 2. 后缀表达式计算\n");			
				printf(" 0. 返回\n");
				printf("请选择:");
				scanf("%d", &cmd);

				if(cmd == 1)
				{
					printf("请输入一个十进制数:");
					scanf("%d", &d);
					printf("二进制为:");
					d_to_b(d);
					printf("\n");
				}

				if(cmd == 2)
				{
					expression();
				}
			}while(cmd!=0);
			cmd = -1;
			break;
		case 9:
			printf(" 本程序为栈的演示程序,由黄彬森设计开发,程序完成了栈的基本功能!\n");		
		default:
			printf("输入选项不存在\n"); 		
		}

	}while(cmd!=0);

	return 0;
}
/*十进制转换为二进制*/
int d_to_b(int d)
{
	SeqStack S;
	int b;

	/*初始化栈*/
	init(&S,32);

	/*d不为0,余数进栈*/
	while(d)
	{
		push(&S, d % 2);
		d /= 2;
	}
	
	/*依次出栈*/
	while(!empty(&S))
	{
		pop(&S,&b);
		printf("%d", b);
	}

	/*销毁栈*/
	destroy(&S);
}


/*后缀表达式计算*/
int expression()
{
	SeqStack S;
	int i;
	int op1, op2;	
	int x;

	char exp[20]; /*后缀表达式*/

	init(&S, 10);

	printf("请输入一个后缀表达式(eg. 56+):");
	scanf("%s", exp);
	for(i=0;i<strlen(exp);i++)
	{
		switch(exp[i])
		{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			/*入栈*/
			push(&S, exp[i]-48);
			printf("%c\n",exp[i]);
			break;
		case '+':
			/*出2个*/
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 + op2;
			push(&S, x);
			break;

		case '*':
			pop(&S, &op1);
			pop(&S, &op2);
			x = op1 * op2;
			push(&S, x);
			break;
		case '-':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2- op1;
			push(&S, x);
			break;
		case '/':
			pop(&S, &op1);
			pop(&S, &op2);
			x =  op2/op1;
			push(&S, x);
			break;	
		}
	}
	pop(&S, &x);
	printf("计算结果为:%s = %d\n", exp, x);
	destroy(&S);
}

3.2  seqstack.h文件代码

typedef int DataType;


typedef struct
{
	DataType *data; /* 堆空间 */
	int maxsize;
	int top;		/* 栈顶指针 */
}SeqStack;


/* 1. 初始化 */
int init(SeqStack *S, int MaxSize);

/* 2. 进(入)栈 */
int push(SeqStack *S, DataType x);

/* 3. 出栈 */
int pop(SeqStack *S, DataType *x);

/* 4. 取栈顶元素 */
int get_top(SeqStack *S, DataType *x);

/* 5. 栈为空?*/
int empty(SeqStack *S);

/* 6. 栈满?*/
int full(SeqStack *S);

/* 7. 销毁*/
int destroy(SeqStack *S);

3.3  seqstack.c文件代码

#include "seqstack.h"


/* 1. 初始化 */
int init(SeqStack *S, int MaxSize)
{
	/*申请内存空间*/
	S->data = (DataType*)malloc(sizeof(DataType)*MaxSize);

	if(!S->data)
	{
		printf("内存申请错误,初始化失败![10001]\n");
		return 10001;
	}
	S->maxsize = MaxSize;
	S->top = -1;
	return 0;
}


/* 2. 进(入)栈 */
int push(SeqStack *S, DataType x)
{
	/*是否满?*/
	if(full(S))
	{
		printf("栈已满!10002\n");
		return 10002;
	}

	S->top++;			/*移动指针*/
	S->data[S->top] = x;/*放入数据*/
	return 0; /*OK*/
}

/* 3. 出栈 */
int pop(SeqStack *S, DataType *x)
{
	/*是否空?*/
	if(empty(S))
	{
		printf("栈为空!10003\n");
		return 10003;
	}

	*x = S->data[S->top];	/*栈顶元素赋值给x*/
	S->top--;				/*移动栈顶指针*/	

	return 0;
}

/* 4. 取栈顶元素 */
int get_top(SeqStack *S, DataType *x)
{
	/*是否空?*/
	if(empty(S))
	{
		printf("栈为空!10003\n");
		return 10003;
	}

	*x = S->data[S->top];	/*栈顶元素赋值给x*/

	return 0;
}

/* 5. 栈为空?*/
int empty(SeqStack *S)
{
	return (S->top == -1)?1:0;
}

/* 6. 栈满?*/
int full(SeqStack *S)
{
	return (S->top == S->maxsize - 1)?1:0;
}


/* 7. 销毁*/
int destroy(SeqStack *S)
{
	free(S->data);
	return 0;
}

3.4  welcome.h文件代码

char welcome[] = "\n\
|     .-.\n\ 
|    /   、         .-.\n\
|   /     、       /   、       .-.     .-.\n\
+--/-------、-----/-----、-----/---、---/---、---/-、-/-、/、/---\n\
| /         、   /       、   /     '-'     '-'              \n\
|/           '-'         '-'                               \n\
";

四、代码运行结果

|     .-.
|    /   、         .-.
|   /     、       /   、       .-.     .-.
+--/-------、-----/-----、-----/---、---/---、---/-、-/-、/、/---
| /         、   /       、   /     '-'     '-'
|/           '-'         '-'
---------顺序栈演示程序-----------
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):1
请输入栈的最大存储空间(MaxSize):10
栈已初始化!
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):2
请输入入栈元素:x=10
元素【10】已入栈!
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):2
请输入入栈元素:x=30
元素【30】已入栈!
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):4
查找到栈顶元素[30]
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):5
栈内存在元素
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):6
栈未满
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):3
确定要出栈(出栈后数据不可恢复,y|n,n)?y
栈顶元素【30】已出栈!
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):7
栈已销毁
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):8
----------8.栈的应用------------
 1. 十进制转换为二进制
 2. 后缀表达式计算
 0. 返回
请选择:1
请输入一个十进制数:102
二进制为:1100110
----------8.栈的应用------------
 1. 十进制转换为二进制
 2. 后缀表达式计算
 0. 返回
请选择:2
请输入一个后缀表达式(eg. 56+):34+4-2*2/
3
4
4
2
2
计算结果为:34+4-2*2/ = 3
----------8.栈的应用------------
 1. 十进制转换为二进制
 2. 后缀表达式计算
 0. 返回
请选择:0
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):9
 本程序为栈的演示程序,由黄彬森设计开发,程序完成了栈的基本功能!
输入选项不存在
 1. 初始化
 2. 入栈
 3. 出栈
 4. 查找栈顶元素
 5. 判断栈为是否空
 6. 判断栈为是否满
 7. 销毁栈
 8. 栈的应用
 9. 帮助
请选择(0~9,0退出):0

--------------------------------
Process exited after 128.2 seconds with return value 0
请按任意键继续. . .

五、小结

栈是一种特殊的顺序结构,栈存储方式以先入后出,后入先出的原则存储数据。入栈时添加元素会置于栈的栈顶,出栈时也需元素从栈顶处出栈,栈可以通过数组和链表实现,链表实现相对简单些,并且链表可以动态扩展,。

六、参考文献

【1】CSDN

【2】数据结构(C语言)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值