二叉树的深度优先遍历与广度优先遍历 [ C++ 实现 ]

深度优先搜索算法(Depth First Search),是搜索算法的一种。是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。

当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。

如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。

作业 - 图1

如右图所示的二叉树:

A 是第一个访问的,然后顺序是 B、D,然后是 E。接着再是 C、F、G。

那么,怎么样才能来保证这个访问的顺序呢?

分析一下,在遍历了根结点后,就开始遍历左子树,最后才是右子树。

因此可以借助堆栈的数据结构,由于堆栈是后进先出的顺序,由此可以先将右子树压栈,然后再对左子树压栈,

这样一来,左子树结点就存在了栈顶上,因此某结点的左子树能在它的右子树遍历之前被遍历。

深度优先遍历代码片段

  1. //深度优先遍历
  2. void depthFirstSearch(Tree root){
  3. stack<Node *> nodeStack; //使用C++的STL标准模板库
  4. nodeStack.push(root);
  5. Node *node;
  6. while(!nodeStack.empty()){
  7. node = nodeStack.top();
  8. printf(format, node->data); //遍历根结点
  9. nodeStack.pop();
  10. if(node->rchild){
  11. nodeStack.push(node->rchild); //先将右子树压栈
  12. }
  13. if(node->lchild){
  14. nodeStack.push(node->lchild); //再将左子树压栈
  15. }
  16. }
  17. }

广度优先搜索算法(Breadth First Search),又叫宽度优先搜索,或横向优先搜索。

是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

如右图所示的二叉树,A 是第一个访问的,然后顺序是 B、C,然后再是 D、E、F、G。

作业 - 图2

那么,怎样才能来保证这个访问的顺序呢?

借助队列数据结构,由于队列是先进先出的顺序,因此可以先将左子树入队,然后再将右子树入队。

这样一来,左子树结点就存在队头,可以先被访问到。

广度优先遍历代码片段

  1. //广度优先遍历
  2. void breadthFirstSearch(Tree root){
  3. queue<Node *> nodeQueue; //使用C++的STL标准模板库
  4. nodeQueue.push(root);
  5. Node *node;
  6. while(!nodeQueue.empty()){
  7. node = nodeQueue.front();
  8. nodeQueue.pop();
  9. printf(format, node->data);
  10. if(node->lchild){
  11. nodeQueue.push(node->lchild); //先将左子树入队
  12. }
  13. if(node->rchild){
  14. nodeQueue.push(node->rchild); //再将右子树入队
  15. }
  16. }
  17. }

完整代码:

  1. /**
  2. * <!--
  3. * File : binarytree.h
  4. * Author : fancy
  5. * Email : fancydeepin@yeah.net
  6. * Date : 2013-02-03
  7. * --!>
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <malloc.h>
  12. #include <Stack>
  13. #include <Queue>
  14. using namespace std;
  15. #define Element char
  16. #define format "%c"
  17. typedef struct Node {
  18. Element data;
  19. struct Node *lchild;
  20. struct Node *rchild;
  21. } *Tree;
  22. int index = 0; //全局索引变量
  23. //二叉树构造器,按先序遍历顺序构造二叉树
  24. //无左子树或右子树用'#'表示
  25. void treeNodeConstructor(Tree &root, Element data[]){
  26. Element e = data[index++];
  27. if(e == '#'){
  28. root = NULL;
  29. }else{
  30. root = (Node *)malloc(sizeof(Node));
  31. root->data = e;
  32. treeNodeConstructor(root->lchild, data); //递归构建左子树
  33. treeNodeConstructor(root->rchild, data); //递归构建右子树
  34. }
  35. }
  36. //深度优先遍历
  37. void depthFirstSearch(Tree root){
  38. stack<Node *> nodeStack; //使用C++的STL标准模板库
  39. nodeStack.push(root);
  40. Node *node;
  41. while(!nodeStack.empty()){
  42. node = nodeStack.top();
  43. printf(format, node->data); //遍历根结点
  44. nodeStack.pop();
  45. if(node->rchild){
  46. nodeStack.push(node->rchild); //先将右子树压栈
  47. }
  48. if(node->lchild){
  49. nodeStack.push(node->lchild); //再将左子树压栈
  50. }
  51. }
  52. }
  53. //广度优先遍历
  54. void breadthFirstSearch(Tree root){
  55. queue<Node *> nodeQueue; //使用C++的STL标准模板库
  56. nodeQueue.push(root);
  57. Node *node;
  58. while(!nodeQueue.empty()){
  59. node = nodeQueue.front();
  60. nodeQueue.pop();
  61. printf(format, node->data);
  62. if(node->lchild){
  63. nodeQueue.push(node->lchild); //先将左子树入队
  64. }
  65. if(node->rchild){
  66. nodeQueue.push(node->rchild); //再将右子树入队
  67. }
  68. }
  69. }
  70. /**
  71. * <!--
  72. * File : BinaryTreeSearch.h
  73. * Author : fancy
  74. * Email : fancydeepin@yeah.net
  75. * Date : 2013-02-03
  76. * --!>
  77. */
  78. #include "binarytree.h"
  79. int main() {
  80. //上图所示的二叉树先序遍历序列,其中用'#'表示结点无左子树或无右子树
  81. Element data[15] = {'A', 'B', 'D', '#', '#', 'E', '#', '#', 'C', 'F','#', '#', 'G', '#', '#'};
  82. Tree tree;
  83. treeNodeConstructor(tree, data);
  84. printf("深度优先遍历二叉树结果: ");
  85. depthFirstSearch(tree);
  86. printf("\n\n广度优先遍历二叉树结果: ");
  87. breadthFirstSearch(tree);
  88. return 0;
  89. }