当前位置:   article > 正文

二叉树的四种遍历详解(先序,中序,后序,层次)_二叉树遍历前序中序后序

二叉树遍历前序中序后序

目录

引言:

1:先序遍历

2.中序遍历

3.后续遍历

4.层次遍历

先序中序后序例题:

例题1:

例题2:

层次遍历例题:

结语:


引言:

二叉树的遍历的概念:二叉树遍历是指按照一定的次序访问二叉树中的所有结点,并且每个结点仅被访问一次的过程。它是二叉树最基本的运算,是二叉树中所有其它运算实现的基础。

为了帮助大家理解各类的遍历过程,下面我给出一个二叉树,下面的各类遍历结果都是根据这张图的图片如下:

二叉树的遍历各类过程:

先序中序和后序都是利用递归来实现的。

层次遍历使用队列实现的

1:先序遍历

(1)访问跟结点

(2)先序遍历左子树

(3)先序遍历右子树

图所示的二叉树的先序序列位ABDGCEF。

先序的代码:

先访问根节点再访问左子树后右子树。

  1. //先序遍历
  2. void PreOrder(BTNode* b)
  3. {
  4. if (b != NULL)
  5. {
  6. printf("%c ", b->data);
  7. PreOrder(b->lchild);
  8. PreOrder(b->rchild);
  9. }
  10. return;
  11. }

2.中序遍历

(1)中序遍历左子树

(2)访问跟结点

(3)中序遍历右子树

图所示的二叉树的中序序列位DGBAECF。

中序的代码:

先访问左子树,再访问根结点,最后是右子树。

  1. //中序遍历
  2. void InOrder(BTNode* b)
  3. {
  4. if (b != NULL)
  5. {
  6. InOrder(b->lchild);
  7. printf("%c ", b->data);
  8. InOrder(b->rchild);
  9. }
  10. return;
  11. }

3.后续遍历

(1)后序遍历左子树

(2)后序遍历右子树

(3)访问根结点

图所示的二叉树的中序序列位GDBEFCA。

后序的代码:

先访问左子树再访问右子树,最后是根结点。

  1. //后序遍历
  2. void PostOrder(BTNode* b)
  3. {
  4. if (b != NULL)
  5. {
  6. PostOrder(b->lchild);
  7. PostOrder(b->rchild);
  8. printf("%c ", b->data);
  9. }
  10. return;
  11. }

4.层次遍历

(1)访问根节点(第一层)

(2)从左到右访问第二层的所有结点。

(3)从左到右访问第三层的所有结点.....第h层的所有结点。

图所示的二叉树的中序序列位ABCDEFG。

层次的代码:

层次是用队列来实现的下面这个代码只是思路,完整代码后续给出。

那么为什么后想到用队列来实现呢?我们可以观察到,二叉树的层次遍历就是按层次从上到下,每一层从左到右的顺序访问树中的全部结点。故某一层中先访问的结点在下一层中它的孩子也先访问,这样不就和我们的队列特性相符合吗,因此层次遍历算法采用一个队列qu来实现。算法中的队列采用顺序队存储结构。

队列的图片如下:

  1. //层次遍历
  2. typedef struct Node
  3. {
  4. BTNode* data[MaxSize];
  5. int front, rear;
  6. }SqQueue;
  7. void LevelOrder(BTNode* b)
  8. {
  9. BTNode* p=NULL;
  10. SqQueue* qu;
  11. qu = InitQueue();
  12. enQueue(qu, b);
  13. while (!EmptyQueue(qu))
  14. {
  15. deQueue(qu, &p);
  16. printf("%c ", p->data);
  17. if (p->lchild != NULL)
  18. enQueue(qu, p->lchild);
  19. if (p->rchild != NULL)
  20. enQueue(qu, p->rchild);
  21. }
  22. DestroyQueue(qu);
  23. }

以上便是各类遍历的基本思路,下面我会结合一下运用遍历的例题来帮助大家理解,因为文章篇幅有限,故例题只给出实现函数部分,没有给出主函数,特别说明最后面我会给出一个主函数(非常完整),大家例题中的代码都能带进去运行,方便大家调试理解由于层次遍历和前面三种遍历实现方法不太一样,故下面的例题会分为,前面三种遍历和层次遍历。

先序中序后序例题:

例题1:

设计一个算法,输出一颗给定二叉树的所有结点。

即输出:GEF结点

对应的函数如下DispLeaf(BTNode*b)

通过判断有无孩子结点来判断他是不是叶子结点(最下面那个结点),如果不是就递归左右子树找叶子。此题三种遍历都能实现,下面代码是先序遍历,如果把if和DispLeaf(b->lchild);交换就变成中序遍历,同理如果把DispLeaf(b->lchild)和 DispLeaf(b->rchild);同时先上移,这样就变成后序遍历。

  1. void DispLeaf(BTNode* b)//求叶子结点
  2. {
  3. if (b != NULL)
  4. {
  5. if (b->lchild == NULL && b->rchild == NULL)
  6. {
  7. printf("%c ", b->data);
  8. }
  9. DispLeaf(b->lchild);
  10. DispLeaf(b->rchild);
  11. }
  12. }

运行结果如下:

例题2:

设计一个算法求二叉树b中第k层的结点个数。

思路如下:函数名为void Lnodenum(BTNode* b, int h, int k, int* n),其中h表示b所指的结点层次,n是引用型参数,由于求第k层的结点个数,在初始调用时,b为根结点指针,h为1,n赋值为0,即调用方式时n=0;Lnodenum(b, 1, k, &t);

采用先序遍历的函数如下,如果想用中序和后序的话按照例题一的修改方法即可。

  1. void Lnodenum(BTNode* b, int h, int k, int* n)
  2. {
  3. if (b == NULL)
  4. {
  5. return;
  6. }
  7. else if (h == k)
  8. {
  9. if(b->data!=' ') *n = *n + 1;
  10. return;
  11. }
  12. else if (h < k)
  13. {
  14. Lnodenum(b->lchild, h + 1, k, n);//特别注意不要&n
  15. Lnodenum(b->rchild, h + 1, k, n);
  16. }
  17. }

运行结果如下:

对照上面给出的二叉树的图大家可以试试。

对应的main函数。

直接将上面的两个函数加进去即可,其中CreateBTree和DispBTree在我的上一篇文章二叉树的基本运算中已经讲的很清楚了,如果有朋友们不是很清楚的话,可以去上一篇文章看看,写的很详细哦。

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. typedef char ElemType;
  5. #define MaxSize 100
  6. typedef struct node
  7. {
  8. struct node* lchild, * rchild;
  9. ElemType data;
  10. }BTNode;
  11. BTNode* CreateBTree(char* str)
  12. {
  13. BTNode* SqStack[MaxSize];
  14. BTNode* b;
  15. BTNode* p = NULL;
  16. b = NULL;
  17. int top = -1;
  18. char ch;
  19. int j = 0;
  20. ch = str[j];
  21. int k = 0;
  22. while (ch != '\0')
  23. {
  24. switch (ch)
  25. {
  26. case '(':k = 1; top++; SqStack[top] = p; break;
  27. case ')':top--; break;
  28. case ',':k = 2; break;
  29. default:
  30. {
  31. p = (BTNode*)malloc(sizeof(BTNode));
  32. p->data = ch;
  33. p->lchild = p->rchild = NULL;
  34. if (b == NULL)
  35. {
  36. b = p;
  37. }
  38. else
  39. {
  40. switch (k)
  41. {
  42. case 1:SqStack[top]->lchild = p; break;
  43. case 2:SqStack[top]->rchild = p; break;
  44. }
  45. }
  46. }
  47. }
  48. j++;
  49. ch = str[j];
  50. }
  51. return b;
  52. }
  53. void DispBTree(BTNode* b)
  54. {
  55. if (b != NULL)
  56. {
  57. printf("%c", b->data);
  58. if (b->lchild != NULL || b->rchild != NULL)
  59. {
  60. printf("(");
  61. DispBTree(b->lchild);
  62. if (b->rchild != NULL) printf(",");
  63. DispBTree(b->rchild);
  64. printf(")");
  65. }
  66. }
  67. }
  68. int main()
  69. {
  70. char str[] = "A(B(D( ,G)),C(E,F))";
  71. BTNode* b = CreateBTree(str);
  72. //DispLeaf(b);
  73. int t = 0;
  74. Lnodenum(b, 1, 3, &t);
  75. printf("%d", t);
  76. //DispBTree(b);
  77. return 0;
  78. }

层次遍历例题:

设计一个算法将二叉树按层次遍历输出:

层次遍历过程是先将根结点进队,在队不空是循环:出队一个结点p并访问它,若它有左孩子,将左孩子进队:若它有右孩子,将有孩子进队。如此操作,直到队空为止。次过程称为基本层次遍历过程,对应的算法代码如下。本身代码不多主要是实现队列挺麻烦的(这就是为什么c语言没有别的语言效率那么高的原因,别的语言有的自带队列)。

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. typedef char ElemType;
  5. #define MaxSize 100
  6. typedef struct node
  7. {
  8. struct node* lchild;
  9. struct node* rchild;
  10. ElemType data;
  11. }BTNode;
  12. typedef struct
  13. {
  14. BTNode* data[MaxSize];
  15. int front, rear;
  16. }SqQueue;
  17. //基本层次遍历算法
  18. SqQueue* InitQueue()
  19. {
  20. SqQueue* obj = (SqQueue*)malloc(sizeof(SqQueue));
  21. obj->front = obj->rear = -1;
  22. return obj;
  23. }
  24. bool enQueue(SqQueue* qu, BTNode* b)
  25. {
  26. qu->rear++;
  27. qu->data[qu->rear] = b;
  28. return true;
  29. }
  30. bool EmptyQueue(SqQueue* qu)
  31. {
  32. return (qu->front == qu->rear);
  33. }
  34. bool deQueue(SqQueue* qu, BTNode** b)
  35. {
  36. qu->front++;
  37. *b = qu->data[qu->front];
  38. return true;
  39. }
  40. void DestroyQueue(SqQueue* qu)
  41. {
  42. free(qu);
  43. }
  44. void LevelOrder(BTNode* b)
  45. {
  46. BTNode* p = NULL;
  47. SqQueue* qu;
  48. qu = InitQueue();
  49. enQueue(qu, b);
  50. while (!EmptyQueue(qu))
  51. {
  52. deQueue(qu, &p);
  53. printf("%c ", p->data);
  54. if (p->lchild != NULL)
  55. enQueue(qu, p->lchild);
  56. if (p->rchild != NULL)
  57. enQueue(qu, p->rchild);
  58. }
  59. DestroyQueue(qu);
  60. }
  61. BTNode* CreateBTree(char str[])
  62. {
  63. BTNode* b = (BTNode*)malloc(sizeof(BTNode));
  64. BTNode* St[MaxSize];
  65. b = NULL;
  66. BTNode* p = NULL;
  67. int top = -1;
  68. char ch;
  69. int j = 0;
  70. ch = str[j];
  71. int k;
  72. while (ch != '\0')
  73. {
  74. switch (ch)
  75. {
  76. case '(':top++; St[top] = p; k = 1; break;
  77. case ')':top--; break;
  78. case ',':k = 2; break;
  79. default:
  80. {
  81. p = (BTNode*)malloc(sizeof(BTNode));
  82. p->data = ch;
  83. p->lchild = p->rchild = NULL;
  84. if (b == NULL)
  85. {
  86. b = p;
  87. }
  88. else
  89. {
  90. switch (k)
  91. {
  92. case 1:St[top]->lchild = p; break;
  93. case 2:St[top]->rchild = p; break;
  94. }
  95. }
  96. }
  97. }
  98. j++;
  99. ch = str[j];
  100. }
  101. return b;
  102. }
  103. int main()
  104. {
  105. char str[] = "A(B(D( ,G)),C(E,F))";
  106. BTNode* b = CreateBTree(str);
  107. LevelOrder(b);
  108. }

以上便是先序中序后序层次遍历的算法及例题。文章到这也就到了尾声啦,感谢观看声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】

推荐阅读
相关标签