当前位置:   article > 正文

数据结构(C语言)代码实现(八)——顺序栈实现&数值转换&行编辑程序&括号分配&汉诺塔

数据结构(C语言)代码实现(八)——顺序栈实现&数值转换&行编辑程序&括号分配&汉诺塔

目录

 参考资料

顺序栈的实现

头文件SqStack.h(顺序栈函数声明)

源文件SqStack.cpp(顺序栈函数实现)

顺序栈的三个应用

数值转换

行编辑程序

顺序栈的实现测试

栈与递归的实现(以汉诺塔为例)


 参考资料

1.本文文章结构参考这篇博客,部分代码也引用自这篇博客。

2021-9-22【数据结构/严蔚敏】【顺序栈&链式栈&迷宫求解&表达式求值】【代码实现算法3.1-3.5】_数据结构表达式求值代码严老师-CSDN博客

2.又搜到一个更靠谱的,这个的引用也用指针替代了。

栈和队列-数据结构与算法(C语言版)_调用pop(&s,&e)函数,让队头数据出队,赋值给参数e,printf输出e-CSDN博客3. 数据结构课本严蔚敏版。

顺序栈的实现

头文件SqStack.h(顺序栈函数声明)

  1. #pragma once
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #define TRUE 1
  6. #define FALSE 0
  7. #define OK 1
  8. #define ERROR 0
  9. #define INFEASIBLE -1
  10. #define OVERFLOW -2
  11. typedef int Status;//Status是函数的类型,其值是函数结果状态代码
  12. typedef int SElemType;
  13. //-----栈的顺序存储表示-----
  14. #define STACK_INIT_SIZE 100 //存储空间初始分配量
  15. #define STACKINCREMENT 10 //存储空间分配增量
  16. typedef struct SqStack {
  17. SElemType* base;//在栈构造之前和销毁之后,base的值为NULL
  18. SElemType* top; //栈顶指针
  19. int stacksize; //当前已分配的存储空间,以元素为单位
  20. }SqStack;
  21. //-----基本操作的函数原型说明-----
  22. Status InitStack(SqStack& S);
  23. //构造一个空栈S
  24. Status DestroyStack(SqStack& S);
  25. //销毁栈S,S不再存在
  26. Status ClearStack(SqStack& S);
  27. //把S置为空栈
  28. Status StackEmpty(SqStack S);
  29. //若栈S为空栈,则返回TRUE,否则返回FALSE
  30. int StackLength(SqStack S);
  31. //返回S的元素个数,即栈的长度
  32. Status GetTop(SqStack S, SElemType& e);
  33. //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
  34. Status Push(SqStack& S, SElemType e);
  35. //插入元素e为新的栈顶元素
  36. Status Pop(SqStack& S, SElemType& e);
  37. //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
  38. Status StackTraverse(SqStack S, void(*visit)(SElemType));
  39. //从栈顶到栈底依次对栈中每个元素调用函数visit()。一旦visit()失败,则操作失败

源文件SqStack.cpp(顺序栈函数实现)

源文件SqStack.cpp是头文件SqStack.h的实现。

  1. #include "SqStack.h"
  2. //-----基本操作的函数算法描述(部分)-----
  3. Status InitStack(SqStack& S) {
  4. //构造一个空栈S
  5. S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
  6. if (!S.base)exit(OVERFLOW);//存储分配失败,警告C6011
  7. S.top = S.base;
  8. S.stacksize = STACK_INIT_SIZE;
  9. return OK;
  10. }
  11. Status DestroyStack(SqStack& S) {
  12. free(S.base);
  13. S.top = S.base = NULL;
  14. S.stacksize = 0;
  15. return OK;
  16. }
  17. Status ClearStack(SqStack& S) {
  18. if (!S.base)return ERROR;
  19. S.top = S.base;
  20. return OK;
  21. }
  22. Status StackEmpty(SqStack S) {
  23. if (S.base == S.top)
  24. return OK;
  25. return ERROR;
  26. }
  27. int StackLength(SqStack s) {
  28. if (!s.base)
  29. return ERROR;
  30. return (int)(s.top - s.base);
  31. }
  32. Status GetTop(SqStack s, SElemType& e) {
  33. //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
  34. if (s.base == s.top)
  35. return ERROR;
  36. e = *(s.top - 1);
  37. return OK;
  38. }
  39. Status Push(SqStack& s, SElemType e) {
  40. //插入元素e为新的栈顶元素
  41. if (!s.base)return ERROR;
  42. if (s.top - s.base >= s.stacksize) {//栈满,追加存储空间
  43. s.base = (SElemType*)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(SElemType));
  44. if (!s.base)exit(_OVERFLOW);//存储分配失败
  45. s.top = s.base + s.stacksize;
  46. s.stacksize += STACKINCREMENT;
  47. }
  48. *s.top++ = e;//*s.top=e; s.top++;
  49. return OK;
  50. }
  51. Status Pop(SqStack& s, SElemType& e) {
  52. //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
  53. if (!s.base || s.top == s.base) return ERROR;
  54. e = *--s.top;//--s.top; e=*s.top;
  55. return OK;
  56. }
  57. Status StackTraverse(SqStack s, void (*visit)(SElemType)) {
  58. SElemType* p = s.base;
  59. if (!s.base)return ERROR;
  60. while (p < s.top)
  61. visit(*p++);
  62. printf("\n");
  63. return OK;
  64. }

顺序栈的四个应用

数值转换

源文件conversion.cpp

  1. #include "SqStack.h"
  2. void conversion() {
  3. //对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
  4. SqStack S;
  5. InitStack(S);//构造空栈
  6. SElemType N,e;
  7. scanf_s("%d", &N);
  8. if (N == 0)//当N为0时下面的while循环不输出
  9. {
  10. printf("%d", N);
  11. return;
  12. }
  13. while (N) {
  14. Push(S, N % 8);
  15. N = N / 8;
  16. }
  17. while (!StackEmpty(S)) {
  18. Pop(S, e);
  19. printf("%d", e);
  20. }
  21. }
  22. int main()
  23. {
  24. conversion();
  25. return 0;
  26. }//算法3.1

测试结果(课本样例)

括号匹配

栈和队列-数据结构与算法(C语言版)_调用pop(&s,&e)函数,让队头数据出队,赋值给参数e,printf输出e-CSDN博客源文件 MatchBrackets.cpp

完整代码

  1. #include "SqStack.h"
  2. /*
  3. * 括号匹配
  4. * 注意将ElemType 修为 char
  5. */
  6. Status MatchBrackets(SqStack& S, char* brackets) {
  7. SElemType ch;
  8. int len = strlen(brackets);
  9. for (int i = 0; i < len; i++) {
  10. if (brackets[i] == '{' || brackets[i] == '[' || brackets[i] == '(') {
  11. Push(S, brackets[i]);
  12. }
  13. if (brackets[i] == '}' || brackets[i] == ']' || brackets[i] == ')') {
  14. if (StackEmpty(S)) {
  15. printf("右括号多于左括号\n");
  16. return ERROR;
  17. }
  18. else {
  19. GetTop(S, ch);
  20. if (ch == '{' && brackets[i] == '}' || ch == '[' && brackets[i] == ']' || ch == '(' && brackets[i] == ')') {
  21. Pop(S, ch);
  22. }
  23. }
  24. }
  25. }
  26. if (!StackEmpty(S))
  27. printf("左括号多于右括号\n");
  28. else
  29. printf("括号匹配成功!");
  30. return OK;
  31. }
  32. int main()
  33. {
  34. SqStack S;
  35. char brackets[81] = { 0 };
  36. //用char* brackets;会报错
  37. InitStack(S);
  38. scanf_s("%s", brackets,sizeof(brackets));
  39. //不知道为什么,不加sizeof(),括号匹配函数len一直为0
  40. //导致输出总是“括号匹配成功”。
  41. MatchBrackets(S, brackets);
  42. return 0;
  43. }

 测试结果

行编辑程序

源文件LineEdit.cpp

本来想两个主函数能不能在同一个工程下运行,结果不可以。接着我把数值转换这个主函数移除,发现可以运行行编辑程序这个代码了。

右键conversion.cpp,点击移除。

接着打开LineEdit.cpp。右键点击源文件,在添加中找到现有项,点击现有项寻找即可(前提是你写了)

下面是完整代码

  1. #include "SqStack.h"
  2. void visit(SElemType e) {
  3. printf("%d ", e);
  4. }
  5. void LineEdit() {
  6. //利用字符栈S,从终端接收一行并传送至调用过程的数据区
  7. SqStack S;
  8. InitStack(S);//构造空栈S
  9. SElemType c;
  10. char ch = getchar();//从终端接收第一个字符
  11. while (ch != EOF) {//EOF为全文结束符,Ctrl+z+回车键对应EOF
  12. while (ch != EOF && ch != '\n') {//一行内
  13. switch (ch) {
  14. case'#':Pop(S, c);
  15. break;//仅当栈非空时退栈
  16. case'@':ClearStack(S);
  17. break;//重置S为空栈
  18. default:Push(S, ch);
  19. break;//有效字符进栈,未考虑栈满情形
  20. }
  21. ch = getchar();//从终端接收下一个字符
  22. }
  23. //将从栈底到栈顶的栈内字符传送至调用过程中的数据区
  24. StackTraverse(S, visit);//课本没有,但我看不到结果,便加上了这个函数
  25. ClearStack(S);//重置S为空栈
  26. if (ch != EOF)ch = getchar();
  27. }
  28. DestroyStack(S);
  29. }
  30. int main()
  31. {
  32. LineEdit();
  33. return 0;
  34. }

测试样例选自课本P49页右下角两行字符,测试结果如下:

此时正常返回。从元素个数看,结果正确,但不直观,所以将SElemType改为char类型。

为了实现行编辑程序,特别修改两处代码(仅在行编辑程序中使用)。

  1. typedef char SElemType;//修改SqStack.h第13行
  2. void visit(SElemType e) {
  3. printf("%c", e);
  4. }//修改LineEdit.cpp第4行

最终结果 

顺序栈的实现测试

源文件test.cpp ,这个是我复制粘贴的我参考的博客。

  1. #include "SqStack.h"
  2. #include <iostream>
  3. using namespace std;
  4. void visit(SElemType e) {
  5. printf("%d ", e);
  6. }
  7. //简单测试主函数
  8. int main() {
  9. SqStack s;
  10. cout << "InitStack" << endl;
  11. InitStack(s);
  12. cout << "StackEmpty" << endl;
  13. StackEmpty(s) ? cout << "yes\n" : cout << "no\n";
  14. cout << "Push" << endl;
  15. for (int i = 1; i <= 6; i++)
  16. Push(s, i);
  17. cout << "StackTraverse" << endl;
  18. StackTraverse(s, visit);
  19. cout << "StackLength" << endl;
  20. cout << StackLength(s) << endl;
  21. cout << "Pop" << endl;
  22. SElemType e;
  23. Pop(s, e);
  24. cout << e << endl;
  25. StackTraverse(s, visit);
  26. cout << "GetTop" << endl;
  27. GetTop(s, e);
  28. cout << e << endl;
  29. return 0;
  30. }

测试结果

栈与递归的实现(以汉诺塔为例)

这里课本的代码没有用栈实现递归,但一直在强调递归函数是通过栈实现的,并从栈的角度解释了递归函数的原理。

源文件hanoi.cpp

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. int C = 0;
  5. void move(char x, int n, char z) {
  6. printf("%d. Move disk %d from %c to %c\n", ++C, n, x, z);
  7. }
  8. void hanoi(int n, char x, char y, char z)
  9. //将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到
  10. //塔座z上,y可用作辅助塔座。
  11. //搬动操作move(x, n, z) 可定义为(c是初值为0的全局变量,对搬动计数):
  12. //printf(" %i. Move disk %i from %c to %c\n", ++c, n, x, z);
  13. {
  14. if (n == 1)
  15. move(x, 1, z);//将编号为1的圆盘从x移到z
  16. else {
  17. hanoi(n - 1, x, z, y);//将x上编号为1至n-1的圆盘移到y,z作辅助塔
  18. move(x, n, z); //将编号为n的圆盘从x移到z
  19. hanoi(n - 1, y, x, z);//将y上编号为1至n-1的圆盘移到z,x做辅助塔
  20. }
  21. }
  22. int main()
  23. {
  24. int n=3;
  25. char A='a', B='b', C='c';
  26. hanoi(n, A, B, C);
  27. return 0;
  28. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/77750
推荐阅读
相关标签
  

闽ICP备14008679号