《数据布局(C语言版)第二版》第五章-树和二叉树(5.4-5.5.1)

[复制链接]
发表于 2026-2-14 08:03:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
5.4 二叉树的性子和存储布局


5.5 遍历二叉树和线索二叉树


5.5.1 遍历二叉树

先序、中序、后序遍历的递归算法

  1. //算法5.1 先序、中序、后序遍历的递归算法
  2. #include <stdio.h>
  3. #include  <stdlib.h>
  4. typedef char TElemType;
  5. typedef struct BiTNode
  6. {
  7.    
  8.    
  9.         TElemType data;
  10.         struct BiTNode* lchild;
  11.         struct BiTNode* rchild;
  12. }BiTNode, * BiTree;
  13. void InitBiTree(BiTree& T);
  14. void CreateBiTree(BiTree& T);
  15. void preOrderTraverse(BiTree& T);
  16. void InOrderTraverse(BiTree& T);
  17. void posOrderTraverse(BiTree& T);
  18. //ABC##DE#G##F###
  19. int main()
  20. {
  21.    
  22.    
  23.         BiTree Tree = NULL;
  24.         InitBiTree(Tree);
  25.         printf("请输入要用二叉链表表示的字符序列: ");
  26.         CreateBiTree(Tree);
  27.         printf("\n二叉链表的先序序列为: ");
  28.         preOrderTraverse(Tree);
  29.         printf("\n二叉链表的中序序列为: ");
  30.         InOrderTraverse(Tree);
  31.         printf("\n二叉链表的后序序列为: ");
  32.         posOrderTraverse(Tree);
  33.         return 0;
  34. }
  35. //初始化二叉树
  36. void InitBiTree(BiTree& T)
  37. {
  38.    
  39.    
  40.         T = NULL;
  41. }
  42. //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
  43. //由于先序遍历的顺序是“根节点-左子树-右子树”,因此仅有先序可以正确创建二叉树,当根结点为空时,令其整个二叉树为空,而不用管左右子树
  44. void CreateBiTree(BiTree& T)
  45. {
  46.    
  47.    
  48.         TElemType ch = '\0';
  49.        
  50.         ch = getchar();  
  51.         /* getchar从键盘获取且只能获取一个字符。
  52.           接收空格和制表符(空格或制表符会被算作一个正常字符读入一次),
  53.           不接收回车,遇到回车即认为本次输入结束。
  54.           但末尾输入的回车会被留在缓存流中,在下一次被getchar读取到(吃掉回车),并将该回车作为本次输入的结束。
  55.         */
  56.         //scanf_s(" %c", &ch); //用scanf_s会将整个字符序列写进ch中,无法进行递归创建二叉树
  57.         /*scanf_s在输入的末尾遇到空白符(空格符、回车符(\n)和制表符(\t)等) 时,都会认为本次输入结束。
  58.           对于参数%d:会忽略缓冲区开头的空白符(空格、回车、制表符等)(无论有几个),只从数字开始读取。
  59.           但对输入末尾的非数字字符,包括空白符,则可能进入无限循环程序,使得无法进行下一次输入;
  60.           对于参数%c:会直接读取缓冲区的第一个字符(无论这个字符是什么)。
  61.           所以一般需要在%c前面加一个空格,利用格式化的输入方式,使得遇到空格的scanf_s认为本次输入已结束,
  62.           直接等待下一次输入,而放弃缓冲区内的所有字符,来跳过上一次输入末尾的换行符。
  63.         */
  64.         if (ch == '#')
  65.         {
  66.    
  67.    
  68.                 T = NULL;
  69.         }
  70.         else
  71.         {
  72.    
  73.    
  74.                 T = (BiTree)malloc(sizeof(BiTNode));
  75.                 T->data = ch;
  76.                 CreateBiTree(T->lchild);
  77.                 CreateBiTree(T->rchild);
  78.         }
  79. }
  80. //先序遍历二叉树
  81. void preOrderTraverse(BiTree& T)
  82. {
  83.    
  84.    
  85.         if (T)  //只有当T不为空时才访问它的成员
  86.         {
  87.    
  88.    
  89.                 printf(" %c", T->data);
  90.                 preOrderTraverse(T->lchild);
  91.                 preOrderTraverse(T->rchild);
  92.         }
  93. }
  94. //中序遍历二叉树
  95. void InOrderTraverse(BiTree& T)
  96. {
  97.    
  98.    
  99.         if (T)
  100.         {
  101.    
  102.    
  103.                 InOrderTraverse(T->lchild);
  104.                 printf(" %c", T->data);
  105.                 InOrderTraverse(T->rchild);
  106.         }
  107. }
  108. //后序遍历二叉树
  109. void posOrderTraverse(BiTree& T)
  110. {
  111.    
  112.    
  113.         if (T)
  114.         {
  115.    
  116.    
  117.                 posOrderTraverse(T->lchild);
  118.                 posOrderTraverse(T->rchild);
  119.                 printf(" %c", T->data);
  120.         }
  121. }
复制代码


先序、中序、后序遍历的非递归算法

  1. //先序、中序、后序遍历二叉树的非递归算法
  2. #include <stdio.h>
  3. #include  <stdlib.h>
  4. typedef char TElemType;
  5. typedef struct BiTNode
  6. {
  7.    
  8.    
  9.         TElemType data;
  10.         struct BiTNode* lchild;
  11.         struct BiTNode* rchild;
  12. }BiTNode, * BiTree;
  13. //链栈的数据结构
  14. typedef struct StackNode
  15. {
  16.    
  17.    
  18.         BiTree TNodeptr;
  19.         struct StackNode* next;
  20. }StackNode, * LinkStack;
  21. void InitStack(LinkStack& S);
  22. void Push(LinkStack& S, BiTree p);
  23. BiTree Pop(LinkStack& S);
  24. BiTree GetTop(LinkStack& S);
  25. int EmptyStack(LinkStack& S);
  26. void InitBiTree(BiTree& T);
  27. void CreateBiTree(BiTree& T);
  28. void preOrderTraverse(BiTree& T);
  29. void InOrderTraverse(BiTree& T);
  30. void posOrderTraverse(BiTree& T);
  31. /* 按先序次序输入二叉树中结点的值:(输入的结尾一定是两个#号)
  32.         ABC##DE#G##F###
  33.         -*a##b##c##
  34.         ABD##E##C##        */
  35. int main()
  36. {
  37.    
  38.    
  39.         BiTree Tree = NULL;
  40.         InitBiTree(Tree);
  41.         char choice = '\0';
  42.         while (1)
  43.         {
  44.    
  45.    
  46.                 printf("请输入要用二叉链表表示的字符先序序列: ");
  47.                 CreateBiTree(Tree);
  48.                 printf("\n二叉链表的先序序列为: ");
  49.                 preOrderTraverse(Tree);
  50.                 printf("\n二叉链表的中序序列为: ");
  51.                 InOrderTraverse(Tree);
  52.                 printf("\n二叉链表的后序序列为: ");
  53.                 posOrderTraverse(Tree);
  54.                 printf("\n是否继续?(y/n):");
  55.                 scanf_s(" %c", &choice);
  56.                 getchar();
  57.                 if (choice != 'y' && choice != 'Y')
  58.                 {
  59.    
  60.    
  61.                         break;
  62.                 }
  63.                 printf("\n\n");
  64.         }
  65.         return 0;
  66. }
  67. //初始化栈
  68. void InitStack(LinkStack& S)
  69. {
  70.    
  71.    
  72.         S = NULL;
  73. }
  74. //元素进栈
  75. void Push(LinkStack& S, BiTree p)
  76. {
  77.    
  78.    
  79.         struct StackNode* r = NULL;
  80.         r = (struct StackNode*)malloc(sizeof(struct StackNode));
  81.         if (!r)
  82.         {
  83.    
  84.    
  85.                 printf("创建新结点时,内存分配失败。");
  86.                 return;
  87.         }
  88.         r->TNodeptr = p;
  89.         r->next = S;
  90.         S = r;
  91. }
  92. //栈顶元素出栈
  93. BiTree Pop(LinkStack& S)
  94. {
  95.    
  96.    
  97.         if (!S)
  98.         {
  99.    
  100.    
  101.                 printf("弹出栈顶元素时,栈不存在。");
  102.                 return NULL;
  103.         }
  104.         struct StackNode* r = S;
  105.         BiTree a = S->TNodeptr;
  106.         S = S->next;
  107.         free(r);
  108.         return a;
  109. }
  110. //获取栈顶元素
  111. BiTree GetTop(LinkStack& S)
  112. {
  113.    
  114.    
  115.         if (!S)
  116.         {
  117.    
  118.    
  119.                 printf("获取栈顶元素时,栈不存在。");
  120.                 return NULL;
  121.         }
  122.         return S->TNodeptr;
  123. }
  124. //判断栈是否为空
  125. int EmptyStack(LinkStack& S)
  126. {
  127.    
  128.    
  129.         if (!S)
  130.         {
  131.    
  132.    
  133.                 return 1;
  134.         }
  135.         else
  136.         {
  137.    
  138.    
  139.                 return 0;
  140.         }
  141. }
  142. //初始化二叉树
  143. void InitBiTree(BiTree& T)
  144. {
  145.    
  146.    
  147.         T = NULL;
  148. }
  149. //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
  150. void CreateBiTree(BiTree& T)
  151. {
  152.    
  153.    
  154.         TElemType ch = '\0';
  155.         ch = getchar();
  156.         if (ch == '#')
  157.         {
  158.    
  159.    
  160.                 T = NULL;
  161.         }
  162.         else
  163.         {
  164.    
  165.    
  166.                 T = (BiTree)malloc(sizeof(BiTNode));
  167.                 T->data = ch;
  168.                 CreateBiTree(T->lchild);
  169.                 CreateBiTree(T->rchild);
  170.         }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表