博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于栈及其应用演示样例
阅读量:6243 次
发布时间:2019-06-22

本文共 4731 字,大约阅读时间需要 15 分钟。

转载请注明出处

http://blog.csdn.net/pony_maggie/article/details/30802249

作者:小马

作为一种经常使用的数据结构, 了解栈对于算法的学习是很必要的。

栈有先进后出的特点,栈底指向数据表中的第一个元素。栈顶指向最后一个元素的下一个位置。

例如以下图所看到的:

 

 

栈和线性表类似。也是有两种存储结构。分别为顺序结构和链式结构。

大部分情况下,栈使用前者。这和它的使用场景有关。由于通常情况下我们不会对栈进行频繁地。随机地插入,删除操作。以下是我用顺序结构实现的栈。这个栈有个特点就是它的通用性,由于我并没有限制它所存储的数据类型,代码例如以下:

//void**其为双指针,意味入栈和出栈的将仅仅是相应数据的地址。而不须要对数据本身进行拷贝typedef struct {	char *base;	char *top;	int elementSize; //元素所点字节大小	int stackSize;	//当前已分配的空间(注意不是元素的实际个数)}ponyStack;int InitStack(ponyStack *stack, int elementSize){	stack->base = (char *)malloc(STACK_INIT_SIZE * sizeof(char)*elementSize);	if (!stack->base)	{		return RET_ERROR;	}	stack->top = stack->base; //为空	stack->stackSize = STACK_INIT_SIZE;	stack->elementSize = elementSize;	return RET_OK;}int ClearStack(ponyStack *stack){	stack->top = stack->base;	return RET_OK;}bool IsEmptyStack(ponyStack stack){	if (stack.top == stack.base)	{		return true;	}	return false;}

这里没有贴出所有的代码。更完整的能够从最后的地址那里下载。

注意elementSize,这个是栈能够做到通用的核心。

不理解的能够再研究一下代码。

 

 

看一个栈的使用演示样例,数制转换。十进制转八进制。

比如(1348)十进制= (2504)八进制,它基于例如以下的原理:

   N             N/8             N%8

  1348        168               4

  168           21                0

   21             2                  5

   2               0                   2

 

所以非常明显,N不断的除8,每次的余数就是结果的当中一个因子,注意先出来的因子是低位的数。能够考虑用栈来保存每次取余的结果。那么出栈的顺序就是实际的结果顺序。代码非常easy:

int decimalToOctonary(int decimalNumber){	double octNumber = 0;	int nCount = 0;	int nTemp = 0;	ponyStack numberStack;	InitStack(&numberStack, 4);	while (decimalNumber)	{		nTemp = (int)decimalNumber%8;		Push(&numberStack, &nTemp);		decimalNumber = decimalNumber/8;	}	nCount = CountOfStack(numberStack);//元素个数也就是位数	while(!IsEmptyStack(numberStack))	{		Pop(&numberStack, &nTemp);		octNumber += (nTemp*pow(10.0, --nCount));	}		DestroyStack(&numberStack);	return (int)octNumber;}

再来看一个行编辑程序的演示样例,用户在终端输入字符。完毕后保存用户的数据区, 由于在输入的过程中可能出错,须要改动,所以不可能每输入一个字符就存入数据区。比較好的做法是先在内存里开一个输入的缓冲区,当用户输入完毕一行后,再存入数据区。在行内能够改动。比如。当用户发现刚输入的一个字符是错的之后。能够再输入一个'#',表示前一个字符是错的,假设发现当前行输入的错误太多。能够输入一个退行符'@',表示当前行都无效,举个样例:

whli#ilr#e(s#*s)

outcha@putchar(*s=#++)

实际有效的字符是这种:

while(*s)

putchar(*s++)

能够把内存里这个输入缓冲区定为栈,正常情况下每输入一个字符直接入栈,假设发现字符是'#',就栈顶pop一次。假设是'@'就清空栈.代码实现例如以下:

void lineEdit(){	char ch = 0;	char chTemp = 0;	ponyStack lineStack;	InitStack(&lineStack, 1);	ch = getchar();	while (ch != EOF)	{		while (ch != EOF && ch != '\n')		{			switch (ch)			{			case '#':				Pop(&lineStack, &chTemp);				break;			case '@':				ClearStack(&lineStack);				break;			default:				Push(&lineStack, &ch);				break;			}			ch = getchar();		}		writeToFile(lineStack);//存数据		ClearStack(&lineStack);//准备接收下一行		if (ch != EOF)		{			ch = getchar();		}	}	DestroyStack(&lineStack);}

最后一个样例是表达式求值的算法。这个在计算器应用中比較多用到。

比方。

求+4*9-16/4

建两个栈,一个存操作数。一个存运算符.为简单起,在运算符栈会预先存一个'#',表示表达式開始。然后以'#'结束。

运算规则是这种:

输入字符,假设是'#'。则结束,假设是操作数,直接进操作数栈。

假设是运算符。则跟栈顶的运算符比較,假设栈顶的优先级低,直接进栈,接收下一字符,假设相等。脱括号。接收下一个字符,假设栈顶的优先级高,pop两个操作数,pop栈内操作符。运算,然后运算的结果进操作数栈。

当前运算符继续跟栈顶比較。

要实现这个代码。首先要有一个表格。存储我们操作符之间的优先级关系,例如以下所看到的:

static char priority[7][7] = {	'>','>','<','<','<','>','>',   // +	'>','>','<','<','<','>','>',   // -	'>','>','>','>','<','>','>',   // *	'>','>','>','>','<','>','>',   // /	'<','<','<','<','<','=',' ',   // (	'>','>','>','>',' ','>','>',   // )	'<','<','<','<','<',' ','=',   // #};// +   -   *   /   (   )   #

然后实现依据上面的思路,实现起来就比較easy了:

int evaluateExpression(){	char chCurrent = 0;	char chOnTop = 0;	char chTemp = 0;	int nResult = 0;	int nTemp = 0;	int a,b;	int nOperandFlag = 0;	ponyStack operatorStack;//运算符栈	ponyStack operandStack; //操作数栈	InitStack(&operatorStack, 1);	chTemp = '#';	Push(&operatorStack, &chTemp);	InitStack(&operandStack, 4);	chCurrent = getchar();	GetTop(operatorStack, &chOnTop);	while ((chCurrent != '#')||(chOnTop != '#'))	{		if (!isOperator(chCurrent))//是操作数,要考虑多位整型数的情况		{			nTemp = nTemp * (int)pow(10.0, nOperandFlag);			nTemp += (int)(chCurrent - '0');			chCurrent = getchar();			nOperandFlag = 1;		}		else		{			if (nOperandFlag == 1)			{				Push(&operandStack, &nTemp);//操作数输入结束,入栈				nOperandFlag = 0;				nTemp = 0;			}						GetTop(operatorStack, &chOnTop);			switch (precede(chOnTop, chCurrent))//比較优先级			{			case '<':		//栈顶的优先级小				Push(&operatorStack, &chCurrent);				chCurrent = getchar();				GetTop(operatorStack, &chOnTop);				break;			case '=':		//脱括号。接收下个字符				Pop(&operatorStack, &chTemp);				chCurrent = getchar();				GetTop(operatorStack, &chOnTop);				break;			case '>':		//栈顶的优先级大,出栈运算,结果入栈				{					Pop(&operandStack, &a);					Pop(&operandStack, &b);					Pop(&operatorStack, &chTemp);					nTemp = operate(a, chTemp, b);					Push(&operandStack, &nTemp);					nTemp = 0;//重置					GetTop(operatorStack, &chOnTop);				}				break;			default:				break;			}					}	}	GetTop(operandStack, &nResult);		DestroyStack(&operatorStack);	DestroyStack(&operandStack);	return nResult;}

代码下载地址:

https://github.com/pony-maggie/StackDemo

http://download.csdn.net/detail/pony_maggie/7499167

你可能感兴趣的文章
为什么我要垂直对齐代码(你也要如此!)
查看>>
《ANSYS Workbench 16.0超级学习手册》——1.4 本章小结
查看>>
微软确认周二更新补丁破坏了 Windows 10 重置功能
查看>>
《Cisco防火墙》一8.4 入站NAT分析
查看>>
流处理框架 Samza 成为 Apache 基金会顶级项目
查看>>
《腾讯iOS测试实践》一一3.4 测试原则
查看>>
结对编程 VS 代码审查:对比开发者文化
查看>>
用消除重复的加密工具备份数据
查看>>
《电路分析导论(原书第12版)》一1.4.1 算法语言
查看>>
PNG 图片处理库 libpng 曝出漏洞,已初步修复
查看>>
Go 开发的 IM 和推送服务 goim
查看>>
高危漏洞预警:WordPress Core 多个高危漏洞
查看>>
《DNS与BIND(第5版)》——1.5 一定要使用DNS吗
查看>>
"挖掘机指数"告诉你不一样的中国经济
查看>>
看麦肯锡如何分析中国城市群
查看>>
《数据分析变革:大数据时代精准决策之道》一1.4 全面看待运营型分析
查看>>
一分钟自我介绍:阿里云CDN
查看>>
《iOS 8开发指南》——第6章,第6.5节实战演练——使用模板Single View Application...
查看>>
【观点】离开了信息化,大数据就是为他人作嫁衣
查看>>
《HTML5+CSS3网页设计入门必读》——1.4 分裂:WHATWG TF
查看>>