姓名:Far_Rainbow
    学号: 202505000X
    专业: 软件工程
    年级:2020级

    实验名称:实验4 顺序栈的基本操作及应用

    实验内容

    (1)实验目的
    通过该实验,让学生掌握栈的相关基本概念,认识栈是插入和删除集中在一端进行的线性结构,掌握栈的“先入后出”操作特点。栈在进行各类操作时,栈底指针固定不动,掌握栈空、栈满的判断条件。

    (2)实验内容
    用顺序存储结构,实现教材定义的栈的基本操作,提供数制转换功能,将输入的十进制整数转换成二进制、八进制或十六进制。

    (3)参考界面
    菜单中包括以下功能:
    1.初始化栈,2.销毁栈,3.清空栈,4.栈判空,5.求栈长度,6.获取栈顶元素,7.插入一个 元素,8.删除一个元素,9输出所有元素,10进制转换。

    要求:自定义的函数中不允许出现提示语和输出语句。

    (4)验收/测试用例
    通过菜单调用各个操作,测试点:

    • 没有初始化前进行其他操作,程序是否能控制住;
    • 初始化一个栈; 判栈空,屏幕显示栈为空; 3个数入栈, 2、4、6; 栈长度,屏幕输出3;
    • 取栈顶元素,再判栈空,然后再判栈长度。让学生知道取栈顶元素不改变栈中的内容,栈顶指针不发生改变;
    • 出栈,再判栈长度和输出栈中内容;(多次出栈,直到栈为空;再出栈,是否提示栈为空) 销毁栈,再做其他操作,判断程序是否能控制;
    • 数制转换,(允许用户输入想把十进制转换成几进制),然后灵活的转换成对应的进制。

    实验类型:验证性

    实验的重难点:入栈和出栈、进制转换(十六进制)

    实验环境:TDM-GCC 4.9.2 64-bit

    实验步骤及完成任务情况

    一、设计思想

    1. 采用模板实现泛型编程,可创建任意数据类型的栈;
    2. 以顺序表为原型实现顺序栈,设立栈顶指针始终指向最后一个元素的下一个地址;
    3. 实现expend()函数,在栈即将溢出时为栈分配新的内存空间;
    4. 使用栈实现进制转换功能

    二、主要源代码

    1. #include <iostream>
    2. #include <string>
    3. #include <map>
    4. #define STACKSIZE 1000
    5. #define STACKINCREMENT 100
    6. using std::cin;
    7. using std::cout;
    8. using std::endl;
    9. template <typename T> class Stack {
    10. private:
    11. T* base;
    12. T* top;
    13. int _length;
    14. int _capacity;
    15. void expand();
    16. public:
    17. void init();
    18. void destroy();
    19. void clear();
    20. Stack() : base(NULL), top(NULL) { }
    21. ~Stack() {destroy(); }
    22. bool isempty() const {return _length > 0 ? 0 : 1; }
    23. bool exist() const {return _capacity > 0 ? 1 : 0; }
    24. int getlength() const {return _length; }
    25. T& getop() const {return * (top-1); }
    26. void push(T const& e);
    27. T pop() {-- _length; return * -- top; }
    28. void traverse() const
    29. {for(T* ptr = top - 1; ptr >= base; -- ptr) cout<<*ptr<<' '; }
    30. };
    31. template <typename T> void Stack<T>::init()
    32. {
    33. base = new T[STACKSIZE];
    34. top = base;
    35. _length = 0;
    36. _capacity = STACKSIZE;
    37. }
    38. template <typename T> void Stack<T>::destroy()
    39. {
    40. delete[] base;
    41. base = top = NULL;
    42. _length = 0;
    43. _capacity = 0;
    44. }
    45. template <typename T> void Stack<T>::clear()
    46. {
    47. top = base;
    48. _length = 0;
    49. }
    50. template <typename T> void Stack<T>::expand()
    51. {
    52. T* newbase = new T[_capacity+STACKINCREMENT];
    53. for(int i = 0; i < _length; ++ i) newbase[i] = base[i];
    54. delete[] base;
    55. base = newbase;
    56. }
    57. template <typename T> void Stack<T>::push(T const& e)
    58. {
    59. if (top - base > _capacity) expand();
    60. * top ++ = e;
    61. ++ _length;
    62. }
    63. void conversion(int a, long long int num)
    64. {
    65. Stack<int> tran;
    66. tran.init();
    67. int tmp;
    68. if (num == 0){
    69. cout<<num;
    70. return;
    71. }
    72. while(num){
    73. tran.push(num % a);
    74. num = num / a;
    75. }
    76. while(!tran.isempty()){
    77. tmp = tran.pop();
    78. switch(tmp){
    79. case 10: cout<<'A';break;
    80. case 11: cout<<'B';break;
    81. case 12: cout<<'C';break;
    82. case 13: cout<<'D';break;
    83. case 14: cout<<'E';break;
    84. case 15: cout<<'F';break;
    85. default: cout<<tmp;
    86. }
    87. }
    88. }
    89. void conversionmenu()
    90. {
    91. std::map<int, std::string> mp;
    92. std::map<int, int> np;
    93. mp[1] = "二进制"; np[1] = 2;
    94. mp[2] = "八进制"; np[2] = 8;
    95. mp[3] = "十六进制"; np[3] = 16;
    96. int n;
    97. long long int num;
    98. char c = 'y';
    99. cout<<"欢迎使用进制转换功能!\n";
    100. cout<<"1 二进制 2 八进制 3 十六进制\n\n";
    101. while(true){
    102. cout<<"\n请选择你想要转换的进制:";
    103. cin>>n;
    104. if (n < 1 || n > 4){
    105. cout<<"请正确输入您的选择!\n";
    106. continue;
    107. }
    108. cout<<"您选择的是十进制转换成"<<mp[n]<<"[y/n]:";
    109. cin>>c;
    110. if (c == 'y') {
    111. cout<<"请输入您想要转换的数:";
    112. cin>>num;
    113. cout<<"转换成"<<mp[n]<<"的数是:";
    114. conversion(np[n], num);
    115. return;
    116. }
    117. else continue;
    118. }
    119. }
    120. int main()
    121. {
    122. cout<<"\n 顺序栈的基本操作\n\n";
    123. cout<<"1---初始化栈\n";
    124. cout<<"2---销毁栈\n";
    125. cout<<"3---清空栈\n";
    126. cout<<"4---栈判空\n";
    127. cout<<"5---求栈长度\n";
    128. cout<<"6---获取栈顶元素\n";
    129. cout<<"7---插入一个元素\n";
    130. cout<<"8---删除一个元素\n";
    131. cout<<"9---输出所有元素\n";
    132. cout<<"10--进制转换\n";
    133. cout<<"\n\t退出,输入一个负数!\n\n";
    134. Stack<int> s;
    135. int e;
    136. while(true){
    137. int myOption;
    138. cout<<"\n请输入操作序号:";
    139. cin>>myOption;
    140. switch(myOption){
    141. case 1:{
    142. if(s.exist()){
    143. cout<<"初始化失败,栈已存在\n";
    144. break;
    145. }
    146. s.init();
    147. cout<<"初始化成功!\n";
    148. break;
    149. }
    150. case 2:{
    151. if (!s.exist()){
    152. cout<<"销毁失败,栈不存在\n";
    153. break;
    154. }
    155. s.destroy();
    156. cout<<"销毁成功!\n";
    157. break;
    158. }
    159. case 3:{
    160. if (!s.exist()){
    161. cout<<"清空失败,栈不存在\n";
    162. break;
    163. }
    164. if (s.isempty()) ;
    165. else s.clear();
    166. cout<<"清空成功!\n";
    167. break;
    168. }
    169. case 4:{
    170. if (!s.exist()){
    171. cout<<"判空失败,栈不存在\n";
    172. break;
    173. }
    174. if (s.isempty()) cout<<"栈为空!\n";
    175. else cout<<"栈非空!\n";
    176. break;
    177. }
    178. case 5:{
    179. if (!s.exist()){
    180. cout<<"请先创建栈!\n";
    181. break;
    182. }
    183. cout<<"栈的长度是"<<s.getlength()<<endl;
    184. break;
    185. }
    186. case 6:{
    187. if (!s.exist()){
    188. cout<<"获取失败,栈不存在\n";
    189. break;
    190. }
    191. if (s.isempty()){
    192. cout<<"栈为空,无栈顶元素!\n";
    193. break;
    194. }
    195. cout<<"栈顶元素是"<<s.getop()<<endl;
    196. break;
    197. }
    198. case 7:{
    199. if (!s.exist()){
    200. cout<<"插入失败,栈不存在!\n";
    201. break;
    202. }
    203. cout<<"请输入待插入元素e\n"<<" e为:";
    204. cin>>e;
    205. s.push(e);
    206. break;
    207. }
    208. case 8:{
    209. if (!s.exist()){
    210. cout<<"删除失败,栈不存在!\n";
    211. break;
    212. }
    213. if (s.isempty()){
    214. cout<<"栈为空,删除失败!\n";
    215. break;
    216. }
    217. else {
    218. e = s.pop();
    219. cout<<"被删除的元素是:"<<e<<endl;
    220. }
    221. break;
    222. }
    223. case 9:{
    224. if (!s.exist()){
    225. cout<<"遍历并输出失败,栈不存在!\n";
    226. break;
    227. }
    228. if (s.isempty()){
    229. cout<<"栈为空!\n";
    230. break;
    231. }
    232. cout<<"栈的所有元素是:";
    233. s.traverse();
    234. cout<<endl;
    235. break;
    236. }
    237. case 10:{
    238. conversionmenu();
    239. cout<<endl;
    240. break;
    241. }
    242. }
    243. if(myOption > 10 || myOption == 0) cout<<"\n请输入小于10的正整数\n\n";
    244. if(myOption < 0){
    245. cout<<"\n退出程序!\n";
    246. break;
    247. }
    248. }
    249. return 0;
    250. }

    实验结果
    实验4 顺序栈的基本操作及应用 - 图1
    实验4 顺序栈的基本操作及应用 - 图2
    实验4 顺序栈的基本操作及应用 - 图3
    实验4 顺序栈的基本操作及应用 - 图4
    实验4 顺序栈的基本操作及应用 - 图5