利用栈和递归实现进制转换——数据结构实验报告

一、实验名称:栈的应用——进制转换

二、实验目的

熟练掌握栈的两种存储方式的具体实现过程,并分别使用递归和非递归两种方式,实现进制转换。

三、实验要求

  1. 顺序栈和链栈两种存储方式任选一种,实现从十进制到八进制的转换。
  2. 用递归的方法实现上述功能。
  3. 改进算法,实现从十进制到N进制的转化(0<N<10,由用户输入确定。)

四、实验环境

(1) 硬件环境:微机一台;

(2) 软件环境:windows7+VC++ 2010/6.0集成开发环境。

五、实验内容及测试分析

   实验一:

  1. 编程思想

(本次编程是利用顺序栈实现从十进制到八进制的转换)

  1. 十进制转换为八进制是利用短除法,然后再进行倒序取余;可以利用栈先进后出的特性,实现目的存储;
  2. 首先调用InitStack( )函数构建一个空栈;
  3. 利用while循环通过调用入栈Push(S,N%8)将N%8的结果压入栈中,循环体内N=N/8,循环结束条件N=0;
  4. 存储结束后,再利用while循环通过调用出栈Pop( )函数依次输出栈顶的值即可实现倒序输出,循环结束条件为栈为空,此时需要调用判空StackEmpty ( )函数;
  5. 在main主函数中输入十进制数N,通过调用进制转换函数即可实现八进制转换。

  (上述函数均已声明定义并实现。)

  1. 程序代码
  2.  主要代码如下:
 void conversion_8(int N)   //十进制转换为八进制

 {

 

  SqStack S;

 

  int e;

 

  InitStack(S);   //构建空栈

 

  while(N){  //N为非0时执行

 

  Push(S,N%8);   //将N对8取余的值压入栈中

 

  N/=8;   //N更新为N/8

 

 }


 cout<<"转化后的八进制数为:";


 while(!StackEmpty(S)){ //判空

 

  Pop(S,e); //依次出栈

 

  cout<<e;

 

 }


 cout<<endl;

 

 } //结束

 

 

3)测试结果及分析

输入数据:45

输出结果:55

结果分析:45%8=5;45/8=5;5%8=5;即结果为55;

         45=5*8+5*1。

   

 

4)运行结果截图

 

5)出现的问题及解决方法

     第一次运行时结果不能正常输出,发现是在定义StackEmpty( )函数时搞反了真值条件,栈为空时返回true,栈为非空则返回false。

  实验二:

1)编程思想

(本次编程是利用递归实现从十进制到八进制的转换)

  1. 十进制转换为八进制是利用短除法,然后再进行倒序取余;这与栈先进后出的特性同出一辙,采用递归算法实现进制转换,递归不需要调用栈,但是体现了栈的思想;
  2. 设置递归出口N=0,即递归的边界;如果N=0,不执行任何操作,递归结束;
  3. 否则:

递归,调用conversion_8(N%8),层层调用,直到N=0,停止,执行下一步操作,输出N%8;

   4.按照先调用后返回的原则,实现“栈”的“先进后出”,即倒序输出。

2)程序代码

主要代码如下:

void conversion_8(int N)  //将十进制N作为实参传入

{


if(N==0){   //N=0是递归结束,不执行任何操作


}


else{  //否则,调用conversion_8(N/8),直到实参N为0停止


conversion_8(N/8);


cout<<N%8;  //输出N%8


}


 }

 3)测试结果及分析

输入数据:63

输出结果:77

结果分析: 63=7*8+7*1;

63%8=7,63/8=7;7%8=7.

4)运行结果截图

 

  1. 出现的问题及解决方法

      由于递归算法的特殊性,换行符不能在函数内部定义,否则会产生输出一个数换一次行的结果,所以要在main函数中输出提示信息及换行符。

  实验三:

1)编程思想

(本次编程是利用递归实现从十进制到其他进制的转换)

  1. 该实验为实验二的改进,即将已确定的八进制转为可以由用户自定义的任意进制,在实验二的基础上增加了一个形参m;
  2. 递归出口:N=0;
  3. 否则:

执行conversion(N/m,m),层层调用,直到实参N的值为0,停止;

执行下一步输出N%m;

     4.  按照先调用后返回的原则,实现“栈”的“先进后出”,即倒序输出。

2)程序代码

 

主要代码如下:

void conversion(int N,int m) //将十进制数N及要转换的进制m传入函数

{


if(N==0){  //递归出口,即N=0时停止


}


else{ //否则,执行conversion(N/m,m)


conversion(N/m,m);


cout<<N%m; //输出N%m


}


 } 

3)测试结果及分析

输入数据:88 2

输出结果:1011000

结果分析: 88=1*2^7+1*2^5+1*2^3;

         88%2=0,88/2=44;

         44%2=0,44/2=22;

         22%2=0,22/2=11;

         11%2=1,11/2=5;

         5%2=1,5/2=2;

         2%2=0,2/2=1;

         1%2=1,1/2=0。

4)运行结果截图

 

  1. 出现的问题及解决方法

   递归调用时在传入N%m的同时,还得传入进制m。

实验四:

1)编程思想

(本次编程是利用递归实现从十进制到其他进制的转换)

  1. 该实验为实验一的改进,即将已确定的八进制转为可以由用户自定义的任意进制,在实验二的基础上增加了一个形参m;
  2. 首先调用InitStack( )函数构建一个空栈;
  3. 利用while循环通过调用入栈Push(S,N%m)将N%m的结果压入栈中,循环体内N=N/m,循环结束条件N=0;
  4. 存储结束后,再利用while循环通过调用出栈Pop( )函数依次输出栈顶的值即可实现倒序输出,循环结束条件为栈为空,此时需要调用判空StackEmpty ( )函数;
  5. 在main主函数中输入十进制数N,以及转换后的进制m,通过调用进制转换函数即可实现进制转换。

 (上述函数均已声明定义并实现。)

2)程序代码

 

主要代码如下:

 void conversion(int N,int m)

 {

 

  SqStack S;  //构建栈

 

  int e;

 

  InitStack(S);  //初始化栈

 

  while(N){  //N不为0执行循环

 

  Push(S,N%m);  //将N%m入栈

 

  N/=m;  //N返回N/m的商

 

 }


cout<<"转化后的"<<m<<"进制数为:";


 while(!StackEmpty(S)){  //S为非空,执行循环体

 

  Pop(S,e);  //栈顶元素出栈

 

  cout<<e;

 

 }


 cout<<endl;

 

 } 

 

3)测试结果及分析

输入数据:65 8

输出结果:101

结果分析: 65=1*8^2+1*8^0;

         65%8=1,65/8=8;

         8%8=0,8/8=1;

         1%8=1,1/8=0.

4)运行结果截图

5)出现的问题及解决方法

   递归调用时在传入N%m的同时,还得传入进制m。

 

六、实验总结

1.实验一中时间复杂度及空间复杂度均为O(logn);实验二中时间复杂度及空间复杂度也均为O(logn)。很明显,两种算法的复杂度都为对数阶,但代码长短及程序可读性却是大相径庭。

2.实验一利用顺序栈实现进制转换,优点是算法逻辑对于初学者而言较容易接受,且过程相较于递归更为具体;缺点在于代码过于冗杂,在实现进制转换的同时需要用到结构体,同时定义构建栈的函数,出栈入栈函数,还有判空函数,程序过于繁琐,可读性较差。

3.实验二利用递归相较于实验一明显代码大大缩短,程序简单明了,结构更为清晰,缺点在于对于初学者较难掌握其中层层调用后的执行顺序,这就要求了对函数调用过程要有很好的掌握。

4.通过上述讨论可以看出,递归程序在执行过程中相当于系统调用了一个隐式栈,递归嵌套调用时遵循的“后调用先返回”的原则在某种意义上正是实现了栈的“先进后出”特性。

5.实验四是在实验一的基础上的改进,实验三是在实验二基础上的改进,实现了十进制转换为任意进制的功能。相比较来说,程序三更简单明了,时间及空间复杂度均为对数阶。就本次实验主题进制转换而言,我更亲睐递归实现,更加简单明了。递归在解决这种解法简单相同的迭代问题上优势更加明显。

 

发布了11 篇原创文章 · 获赞 9 · 访问量 5989
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览