栈的应用 十进制转换为其他进制的方法
栈,为我们提供了LIFO数据存储方法,但是这种方法到底有什么实际价值呢?如果你学过汇编语言,就会发现栈真的very very important。windowns中的函数调用之所以能够完成,就是用了栈的存储方式,想一想,为什么执行完函数或者过程后,就会紧接着执行函数下边的语句?有的人说了,你写的代码就是一行挨着一行,当然顺序执行了。或许你这种说法没有问题,但是从程序底层探究一下,你就会发现windows是采用栈的方式来操作函数。简单的说,在执行函数的时候,先将程序在内存中的起始地址压入栈,然后在栈中开辟临时变量,执行完毕后,释放临时变量,弹出程序地址,并将EIP(指令指针)指到压栈时入口地址的下一行。
刚才说了栈的底层应用,但是在现实应用有哪些方面呢?先介绍一个简单的,十进制转换到其他任意进制的问题。
书上的解释为:N = (N div d)*d + N mod d;
相信很多人都看不懂,我在这里翻译一下,div是整除,mod是求余数。就是循环求余数,过程如下:
假设输入十进制数字100,要得到8进制的结果。
第一步: 100 / 8 = 12
第二步: 100 % 8 = 4
第三步: 将 4 压入栈
第四步: 12 / 8 = 1
第五步: 12 % 8 = 4
第六步: 将 4 压入栈
第七步: 1 / 8 = 0
第八步: 1 % 8 = 1
第九步: 将1压入栈
到这里,栈中就三个数字,分别为4-4-1,由于栈的LIFO特性,就只要将栈中的数据依次弹出就行,显示的结果是144。敲黑板了,依次弹出的仅仅是显示结果,并没有将数据保存到变量中,如果你要得到144这个变量,还需要将依次弹出的数据乘以10的N次方,N从哪里来?
两种方法。
1.从栈的结构中size中得到,顺序链表中的size是个固定数值,这个值恐怕不能用,需要在前边压入栈的时候添加一个变量,记录压栈的次数,这个次数就是N。
2.用链式存储方式中的结构size,这个size是栈的实际大小,增减会改变size的值。
我用了第一种方式获得变量,仅供参考,先看看结果。
好了,上代码,关于栈的初始化,参看前边的博客:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include"sqstack.h"
void conversion()
{
SqStack SStack;
int num = 0;
int conv = 0;
int e;
int i = -1; //设置为-1,为什么?试试就知道了
int result = 0;
Init_Stack(&SStack); //初始化栈
printf("请输入一个数字(输入完成回车确认):"); //输入源数据
scanf_s("%d", &num);
printf("请输入要转换的进制(输入完成回车确认):"); //输入将要进制
scanf_s("%d", &conv);
while (num) //循环压栈
{
Push(&SStack, num % conv);
num = num / conv;
i++;
}
printf("10进制转换为%d进制的结果为(仅显示):",conv);
while (!IsStackEmpty(&SStack)) //循环取出
{
Pop(&SStack, &e);
printf("%d", e);
result += e * pow(10, i--); //重点:将栈中的数据转换为变量中保存的值
}
printf("\n");
printf("10进制转换为%d进制的结果为(变量显示):%d\n", conv,result);
DestoryStack(&SStack); //销毁栈
}
int main()
{
conversion();
system("pause");
}