详解顺序栈

顺序栈的定义以及特点

定义:

顺序栈(Sequential Stack)是一种基于数组实现的栈结构。栈是一种后进先出(LIFO)的数据结构,只能在栈顶进行插入和删除操作。顺序栈的定义如下:

  1. 数据结构:顺序栈由一个固定大小的数组和一个指向栈顶的指针组成。

  2. 操作:

    • 初始化:创建一个空栈,将栈顶指针指向-1。
    • 入栈(Push):将元素压入栈顶,栈顶指针加1。
    • 出栈(Pop):将栈顶元素弹出,栈顶指针减1。
    • 获取栈顶元素(Top):返回栈顶元素的值,但不删除。
    • 判空(IsEmpty):判断栈是否为空,即栈顶指针是否为-1。
    • 判满(IsFull):判断栈是否已满,即栈顶指针是否达到数组的最大索引。

特点:

顺序栈的特点如下:

  1. 存储效率高:顺序栈使用数组来存储数据,因此存储效率高,不需要额外的指针域。

  2. 访问速度快:由于栈的特性,只能在栈顶进行插入和删除操作,因此访问速度快。

  3. 需要预先分配固定大小的内存空间:顺序栈需要预先分配一定大小的数组来存储数据,因此需要提前确定栈的最大容量。

  4. 容量固定:由于数组大小是固定的,顺序栈的容量是固定的,无法动态扩展。

  5. 可能存在溢出问题:当栈满时,再进行入栈操作会导致栈溢出。

总之,顺序栈是一种简单、高效的栈实现方式,适用于已知大小的栈场景。但需要注意容量的限制和溢出问题。

顺序栈的基本运算

包括初始化、入栈、出栈、获取栈顶元素、判空和判满。下面是对每个运算的详细描述:
  1. 初始化(Init):创建一个空栈,将栈顶指针指向-1。

  2. 入栈(Push):将元素压入栈顶,栈顶指针加1。

    • 首先判断栈是否已满(IsFull)。
    • 如果栈未满,则将元素放入栈顶位置(栈顶指针加1),并将元素存入数组中。
  3. 出栈(Pop):将栈顶元素弹出,栈顶指针减1。

    • 首先判断栈是否为空(IsEmpty)。
    • 如果栈非空,则将栈顶元素取出并返回(栈顶指针减1)。
  4. 获取栈顶元素(Top):返回栈顶元素的值,但不删除。

    • 首先判断栈是否为空(IsEmpty)。
    • 如果栈非空,则返回栈顶位置的元素值。
  5. 判空(IsEmpty):判断栈是否为空,即栈顶指针是否为-1。

    • 如果栈顶指针为-1,则表示栈为空,返回真(True)。
    • 否则,栈非空,返回假(False)。
  6. 判满(IsFull):判断栈是否已满,即栈顶指针是否达到数组的最大索引。

    • 如果栈顶指针等于数组的最大索引,则表示栈已满,返回真(True)。
    • 否则,栈未满,返回假(False)。

以上是顺序栈的基本运算,它们共同构成了对栈的常用操作。通过这些运算,可以实现栈的基本功能,如入栈、出栈、获取栈顶元素等。需要注意的是,在进行入栈和出栈操作时,需要先判断栈是否已满或为空,以避免溢出或下溢的问题。

顺序栈的实现

初始化栈

/* 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;
}

顺序栈的应用部分

/*十进制转换为二进制*/
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);
}

运行截图

完整Demo

main.c部分

#include <stdio.h>
#include <string.h>
#include "seqstack.c"
#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);
}

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;
}

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);

welcome.h部分

char welcome[] = "\n\
                               ............\n\                     
                            ................\n\                   
                           ..................\n\                  
                          ....................\n\                 
                          ....................\n\                 
                           ..................\n\                  
                       ....\ ............../\n\                   
   ...........      .........................\n\                  
 ..............\  /......../######\....../###\.\n\                
................v.........##########\...#######\n\               
..........................|######/..\##.|####/.\#|       ....\n\  
..................#####\.,|######....##.|####...#|     .......\n\ 
................|########.|######....##.|####...#|     .......\n\ 
...............#########_|######\../##.|####\./#|   /##\....\n\   
 ..............###############################nn\/#######^\n\     
   \........./ \########~##############nnnnn.###########/\n\      
                ########|##########nnnnn.##############/\n\       
                 #######| \###########################/\n\        
                  \###.##\    \######################\n\          
                    \##.##\   ___   \#############/\n\            
                       \.##\/.../..\         /##/\n\              
                          \##\/..../     /####/\n\                
                             \#############/\n\
                   Welcome to the mouse program\n\n";

顺序栈学习小结

学习顺序栈是学习数据结构中的重要一步。顺序栈是一种简单、高效的栈实现方式,适用于已知大小的栈场景。学习顺序栈可以帮助我们理解栈的基本概念和操作,并能够灵活运用栈来解决实际问题。

在学习顺序栈时,我们需要掌握以下几个关键点:

  1. 栈的特点:顺序栈具有后进先出(LIFO)的特点,只能在栈顶进行插入和删除操作。

  2. 栈的基本运算:顺序栈的基本运算包括初始化、入栈、出栈、获取栈顶元素、判空和判满等操作。

  3. 存储结构:顺序栈使用数组来存储数据,因此存储效率高,不需要额外的指针域。

  4. 容量限制和溢出问题:顺序栈需要预先分配一定大小的数组来存储数据,因此容量是固定的。当栈满时,再进行入栈操作会导致栈溢出。

  5. 应用场景:顺序栈适用于已知大小的栈场景,如表达式求值、括号匹配、逆波兰表达式等问题。

通过学习顺序栈,我们能够加深对栈的理解,并能够将栈的概念和操作应用到实际问题中。同时,顺序栈也是其他栈的实现方式的基础,对于后续学习其他栈的实现方式也具有重要的参考价值。

参考文献

【1】李刚 刘万辉 “数据结构”(c语言)
【2】百度百科(百度文库)查询
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值