当前位置:   article > 正文

二叉查找树(BST)及二叉树的遍历_bst的前序遍历 中序遍历和后序遍历

bst的前序遍历 中序遍历和后序遍历

二叉查找树(BST)及二叉树的遍历

一、二叉查找树(BST)

1、二叉查找树的特征

  二叉查找树(BST)也称为二叉搜索树或二叉排序树。二叉查找树的节点包含键值key。二叉查找树或者是一棵空树,否则要求:

1. 若它的左子树不为空,那么左子树上所有节点的key都小于根节点的key。

2. 若它的右子树不为空,那么右子树上所有节点的key都大于根节点的key。

. 它的左右子树也分别为二叉排序树。 
这里写图片描述

2、二叉查找树的建立、查找、插入和删除

1)递归建立二叉查找树

  1. btree creat_tree(btree root, int val)
  2. {
  3. if (root == nullptr)//如果为空的二叉树,便将新的节点设定为根节点
  4. {
  5. root = new Binary_tree;
  6. root->data = val;
  7. root->left = nullptr;
  8. root->right = nullptr;
  9. }
  10. else if (root->data < val)//如果新值比节点值大,递归地建立右子树
  11. root->right = creat_tree(root->right, val);
  12. else if (root->data > val)//如果新值比节点值小,递归地建立左子树
  13. root->left = creat_tree(root->left, val);
  14. else
  15. exit(-1);
  16. return root;
  17. }

(2)查找节点

  1. btree search_tree(btree ptr, int val)
  2. {
  3. while(1)
  4. {
  5. if(ptr == nullptr)//没找到就返回NULL
  6. return nullptr;
  7. if(ptr->data == val)//节点值等于查找值
  8. return ptr;
  9. else if(ptr->data > val)//查找值比节点值小,向左子树搜索
  10. ptr = ptr->left;
  11. else
  12. ptr = ptr->right;//查找值比节点值大,向右子树搜索
  13. }
  14. }
  15. //查找值最小的节点
  16. btree findmin_tree(btree root)
  17. {
  18. if (root == nullptr)//首先判断是否为空树
  19. return nullptr;
  20. if (root->left == nullptr)
  21. return root;
  22. else
  23. return findmin_tree(root->left);//使用递归判断
  24. }
  25. //查找值最大的节点
  26. btree findmax_tree(btree root)
  27. {
  28. if (root != nullptr)//首先判断是否为空树
  29. while (root->right != nullptr)//通过循环判断
  30. root = root->right;
  31. return root;
  32. }

(3)插入节点

 

  1. btree insert_tree(btree root, int val)
  2. {
  3. if (search_tree(root, val) == nullptr)
  4. {
  5. if (root == nullptr)
  6. creat_tree(root, val);//如果树为空,则创建树
  7. else if (val < root->data)
  8. //递归插入到左子树
  9. root->left = insert_tree(root->left, val);
  10. else if (val > root->data)
  11. //递归插入到右子树
  12. root->right = insert_tree(root->right, val);
  13. }
  14. }

(4)删除节点

这里写图片描述

  1. btree remove_tree(btree root, int val)
  2. {
  3. btree bt = search_tree(root, val);
  4. if (bt != nullptr)
  5. {
  6. if (val < root->data)//只有左子树
  7. root->left = remove_tree(root->left, val);
  8. else if (val > root->data)//只有右子树
  9. root->right = remove_tree(root->right, val);
  10. //左右子树都有
  11. else if (root->left != nullptr && root->right != nullptr)
  12. {
  13. //把右子树的最小值复制到当前节点
  14. root->data = findmin_tree(root->right)->data;
  15. //把最小值节点删除
  16. root->right = remove_tree(root->right, root->data);
  17. }
  18. else
  19. {
  20. //只有左子树或者右子树
  21. root = (root->left != nullptr)? root->left : root->right;
  22. }
  23. }
  24. }

二、二叉树的遍历

  遍历二叉树,就是以某种方式逐个“访问”二叉树的每一个节点。“访问”是指对节点的进行某种操作,例如输出节点的值。根据访问树根的顺序,我们有三种方式遍历二叉树:

1. 前序遍历:树根->左子树->右子树

2. 中序遍历:左子树->树根->右子树

3. 后序遍历:左子树->右子树->树根

1、前序遍历

  先访问根节点,再遍历左子树,最后遍历右子树;并且在遍历左右子树时,仍需先访问根节点,然后遍历左子树,最后遍历右子树。 
  例如下图中二叉树前序遍历节点访问顺序为ABDGHCEIF: 
这里写图片描述

2、中序遍历

  先遍历左子树、然后访问根节点,最后遍历右子树;并且在遍历左右子树的时候。仍然是先遍历左子树,然后访问根节点,最后遍历右子树。 
  例如前图中二叉树中序遍历节点访问顺序为GDHBAEICF: 
这里写图片描述

3、后序遍历

  先遍历左子树,然后遍历右子树,最后访问根节点;同样,在遍历左右子树的时候同样要先遍历左子树,然后遍历右子树,最后访问根节点。前图后序遍历结果如下。 
  例如前图中二叉树后序遍历节点访问顺序为GHDBIEFCA: 
这里写图片描述

4、确定唯一的二叉树

  在二叉树的三种遍历方式中,如果有中序与前序的遍历结果或者中序与后序的遍历结果,即可从这些结果中得到唯一的二叉树。

  确定唯一二叉树的方式:

1. 首先根据前序遍历的首元素或者后序遍历的尾元素,在中序遍历确定根节点。

. 随后根据该根节点在中序遍历中确定左右子树。

三、前序、中序、后序遍历的递归和非递归实现

1、递归实现

  1. void inorder(btree ptr)//中序(输出根节点次序)遍历(递归实现)
  2. {
  3. if (ptr != nullptr)
  4. {
  5. inorder(ptr->left);
  6. cout << ptr->data << " ";
  7. inorder(ptr->right);
  8. }
  9. }
  10. void preorder(btree ptr)//前序遍历(递归实现)
  11. {
  12. if (ptr != nullptr)
  13. {
  14. cout << ptr->data << " ";
  15. preorder(ptr->left);
  16. preorder(ptr->right);
  17. }
  18. }
  19. void postorder(btree ptr)//后序遍历(递归实现)
  20. {
  21. if (ptr != nullptr)
  22. {
  23. postorder(ptr->left);
  24. postorder(ptr->right);
  25. cout << ptr->data << " ";
  26. }
  27. }

2、非递归实现(使用栈)

  1. //非递归中序遍历(左节点->根节点->右节点)思想:即用栈实现
  2. // 因为中序遍历二叉树的特点,所以在当前节点cur不为空或栈不为空的条件下(在该条件下的原因:该条件说明
  3. // 未遍历完二叉树),开始执行循环体,进行遍历:
  4. //(1)从当前节点cur开始,以cur为循环条件,当cur不为空时,将cur入栈,然后以cur=cur->_left跟进,直至
  5. // 将该二叉树的最左节点入栈后,入栈操作结束
  6. //(2)取栈顶节点:先保存该节点(用top保存该节点的原因:还要考虑该节点的右孩子)并输出该节点的值,
  7. // 然后执行栈的pop操作。
  8. //(3)继续以top->_right为cur值,转(1)操作.
  9. void inorder2(btree ptr)//中序遍历的非递归实现
  10. {
  11. stack<btree> st;
  12. while (ptr != nullptr || !st.empty())
  13. {
  14. while (ptr != nullptr)
  15. {
  16. st.push(ptr);
  17. ptr = ptr -> left;
  18. }
  19. btree tp = st.top();
  20. cout << tp -> data << " ";
  21. st.pop();
  22. ptr = tp -> right;
  23. }
  24. }
  25. //非递归先序遍历(根节点->左节点->右节点)思想:即用栈实现
  26. //遍历二叉树的前提条件是:该二叉树不为空。在满足该条件的情况下,进行以下步骤:
  27. //1.先将二叉树的根节点push进栈。
  28. //2.在该栈不为空的条件下,执行一个循环(先用top保存栈顶元素,再对栈进行pop操作,因为栈具有后进先出的特点
  29. // ,所以先对top->_right进行判断是否入栈,再对top->_left进行判断是否入栈)。
  30. //3.当栈为空时,先序遍历该二叉树结束。
  31. void preorder2(btree ptr)//前序遍历的非递归实现
  32. {
  33. stack<btree> st;
  34. if (ptr != nullptr)
  35. {
  36. st.push(ptr);
  37. }
  38. while (!st.empty())
  39. {
  40. btree tp = st.top();
  41. st.pop();
  42. cout << tp -> data << " ";
  43. if (tp->right != nullptr)
  44. st.push(tp->right);
  45. if (tp->left != nullptr)
  46. st.push(tp->left);
  47. }
  48. }
  49. //非递归后序遍历(左节点->右节点->根节点)思想:即用栈实现
  50. //(1)在当前节点cur不为空或栈不为空的条件下(在该条件下的原因:该条件说明未遍历完二叉树)。
  51. //(2)从当前节点cur开始,以cur为循环条件,当cur不为空时,将cur入栈,然后以cur=cur->_left跟进,直至
  52. // 将该二叉树的最左节点入栈后,入栈操作结束。取栈顶节点top:先保存该节点(用top保存该节点的原因:
  53. // 还要考虑该节点的右孩子),
  54. //(3)若top->_right==NULL || lastVisited == top->_right,则输出top->_value,执行栈的pop操作,并执行lastVisited = top(
  55. // 用lastVisited保存最近一个所输出的节点,待到下一次同样的操作时,若lastVisited == top->_right,则
  56. // 说明top的右节点已经访问过了,可以访问top了,否则会陷在cur = top->_right这步操作里);
  57. //(4)若条件(3)不满足,则继续以top->_right为cur值,转(1)操作.
  58. void postorder2(btree ptr)//后序遍历的非递归实现
  59. {
  60. stack<btree> st;
  61. btree lastVisited = nullptr;
  62. while (ptr != nullptr || !st.empty())
  63. {
  64. while (ptr != nullptr)
  65. {
  66. st.push(ptr);
  67. ptr = ptr -> left;
  68. }
  69. btree tp = st.top();
  70. if (tp->right == nullptr || lastVisited == tp->right)
  71. {
  72. st.pop();
  73. cout << tp -> data << " ";
  74. lastVisited = tp;
  75. }
  76. else
  77. ptr = tp->right;
  78. }
  79. }

参考:

  https://blog.csdn.net/xiaotan2011929/article/details/61427919 
  http://www.cnblogs.com/QG-whz/p/5168620.html

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

闽ICP备14008679号