• Day6:无序二叉树的插入以及遍历(前/中/后序)


    /*基础概念参照:*/

    数据结构 --- c语言二叉树基础(无序二叉树)https://blog.csdn.net/weixin_60569662/article/details/123083815

    pre:树框架的构建

    1. template<class T>
    2. struct Node
    3. {
    4. T data;
    5. Node* pLeft;//左孩子
    6. Node* pRight;//右孩子
    7. Node(const T& data)
    8. {
    9. this->data = data;
    10. pLeft = pRight = nullptr;
    11. }
    12. };
    13. template<class T>
    14. class Tree
    15. {
    16. public:
    17. Tree() { pRoot = nullptr; }
    18. ~Tree() { _clear(pRoot); }
    19. void clear(Node*pDel)
    20. {
    21. _clear(pDel)
    22. }
    23. bool insert(const T& data)
    24. {return _insert(data,pRoot); }
    25. void travel(int type);//-1前序遍历 0中序遍历 1后序遍历
    26. private:
    27. Node* pRoot;
    28. private: //也可以用二级指针完成,引用更常用一点
    29. bool _insert(const T& data,Node*&pRoot);
    30. void _clear(Node* pDel);
    31. //先序
    32. void _preTravel(TreeNode* root);
    33. //中序
    34. void _midTravel(TreeNode* root);
    35. //后序
    36. void _lstTravel(TreeNode* root);
    37. };

    一、无序二叉树的插入

    注意:①利用二叉树的递归特性(不断成为新的根节点

               ②利用Ddata来限制是插左孩子还是右孩子->注意判断放置的位置!!同时利用bool返回值来控制。

               ③第一个if插成功了,记得return true;

    1. template<class T>
    2. bool Tree::_insert(const T& data, Node*& pRoot)
    3. {
    4. //递归终止条件
    5. if (pRoot == nullptr)
    6. {
    7. Node* pNew = new Node(data);
    8. pRoot = pNew;
    9. return true;
    10. }
    11. //控制插入左孩子还是右孩子
    12. if (Ddata == pRoot->data)return false;
    13. //递归
    14. if (_insert(data, pRoot->pLeft))return true;
    15. return _insert(data, pRoot->pRight);
    16. }

     测试代码:

    1. Tree<int> mytree;
    2. int arr[] = { 1,2,Ddata,4,5,Ddata,Ddata,Ddata,3,Ddata,6,Ddata,7,Ddata,Ddata};
    3. for (auto v : arr)
    4. {
    5. mytree.insert(v);
    6. }

     实现的二叉树如下图:

     二、无序二叉树的遍历

    1.简述:

    • 前序遍历:根在前面,根左右

    • 中序遍历:左根右

    • 后序遍历:根在后面,左右根

    2.以上图的二叉树为例,三种结果为:

            前序遍历
            1 2 4 5 3 6 7
            中序遍历
            2 5 4 1 3 6 7
            后序遍历
            5 4 2 7 6 3 1

    3.利用递归,代码的实现十分简洁   

    1. template<class T>
    2. void Tree::travel(int type)
    3. {
    4. switch (type)
    5. {
    6. case -1:
    7. cout << "前序遍历" << endl;
    8. _preTravel(pRoot); break;
    9. case 0:
    10. cout << "中序遍历" << endl;
    11. _midTravel(pRoot); break;
    12. case 1:
    13. cout << "后序遍历" << endl;
    14. _lstTravel(pRoot); break;
    15. }
    16. cout << endl;
    17. }
    18. template<class T>
    19. void Tree::_preTravel( Node*& root)
    20. {//前序遍历:根左右
    21. if (root == nullptr)return;//递归终止条件一定不能忘记
    22. cout << root->data << " ";
    23. _preTravel(root->pLeft);
    24. _preTravel(root->pRight);
    25. }
    26. template<class T>
    27. void Tree::_midTravel( Node*& root)
    28. {//前序遍历:左根右
    29. if (root == nullptr)return;
    30. _midTravel(root->pLeft);
    31. cout << root->data << " ";
    32. _midTravel(root->pRight);
    33. }
    34. template<class T>
    35. void Tree::_lstTravel( Node*& root)
    36. {//前序遍历:左右根
    37. if (root == nullptr)return;
    38. _lstTravel(root->pLeft);
    39. _lstTravel(root->pRight);
    40. cout << root->data << " ";
    41. }

     注:因为有叶子结点(Ddata=9999)作为切换左右孩子的条件->所以,在此输出的时候,在上面的代码可以再添加一下控制,不让叶子结点的data输出。(为了代码的简洁可读性,此处没加)

    三、无序二叉树遍历的理论分析

    1.利用递归的思想,里面最先出来+前中后序遍历的限制,就很容易分析出!!!

            前序遍历
            1 2 4 5 3 6 7
            中序遍历
            2 5 4 1 3 6 7
            后序遍历
            5 4 2 7 6 3 1

     时时自测一下,以中序为例,很容易犯错的是,F在H前面,递归到最深处,也得满足左(H)根(F)右,H必定在F的左侧。

    2.已知中序+前or后可推导出原树

        已知 中序遍历 和 先序遍历  能推导出  后序遍历
        已知 中序遍历 和 后序遍历  能推导出  先序遍历
        已知 先序遍历 和 后序遍历 , 推导不出

     其他参考:二叉树的前序、中序、后序遍历(个人笔记) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/73438175

    四、无序二叉树的释放

    1. template<class T>
    2. void Tree::_clear(Node*& pDel)
    3. {
    4. //错误思路:遍历一遍,依次释放
    5. //利用递归特性:逐一释放
    6. if (pDel == nullptr)return;//注意递归终止条件
    7. _clear(pDel->pLeft);
    8. _clear(pDel->pRight);
    9. delete pDel;
    10. pDel = nullptr;
    11. }

    利用递归特性->递归释放!!!!!

  • 相关阅读:
    Vue3——网站整体布局、用户动态页面(下)
    Elasticsearch实战(十八)--ES搜索Doc Values/Fielddata 正排索引 深入解析
    mac电脑如何安装python及环境搭建
    react中遇到的分页问题
    谷粒商城一
    Mysql基础 (二)
    《前端》css总结(上)
    多线程学习笔记
    如何使用 Xcode 13+ 新的列断点(Column Breakpoints)让中断位置更加精确制导
    【听课笔记】复旦大学遗传学_01孟德尔遗传
  • 原文地址:https://blog.csdn.net/zjjaibc/article/details/125901676