zoukankan      html  css  js  c++  java
  • C++11 binary Tree


    二叉树类: BinaryTree
    树节点类: Node

       包含一些常用的操作:

      1. 创建二叉树: 将vector数据构建成二叉树结构  A:按节点左右加入  B:按层级一层层构建

           2. 二叉树反转

           3. 二叉树是否对称,即左右是否成镜像

           4. 前序遍历

           5. 中序遍历

           6. 后续遍历

           7. 层级遍历

    
    

    #include <string>
    #include <memory>
    #include <vector>
    #include <iostream>
    #include <sstream>
    #include <queue>


    ///////////////
    class Node { public: Node(int data, std::string strData = "") :m_nData{ data } ,m_string{ strData } ,m_pLeftChild{ nullptr } ,m_pRightChild{ nullptr }{} virtual ~Node(){} public: int getData() { return m_nData; } void setData(int data) { m_nData = data; } std::string getString() { return m_string;} void setString(std::string strData) { m_string = strData; } public: bool operator < (Node node) { if (m_nData < node.getData()) return true; else return false; } public: std::shared_ptr<Node> m_pLeftChild; std::shared_ptr<Node> m_pRightChild; //value private: int m_nData; std::string m_string; }; ////////////////////////////////////////////////////// class BinaryTree { public: BinaryTree(){} virtual ~BinaryTree(){} public: //创建二叉树: 通过比较节点大小方式插入,小于往左,大于往右 int create(std::vector<int> vecData) { for (auto itor : vecData) { std::ostringstream ostrStream; ostrStream << "" << itor << std::endl; std::shared_ptr<Node> pNode = std::make_shared<Node>(itor, ostrStream.str()); //通过返回值返回root,使用引用传入参数,修改root也是一种方式。 addNode(m_pRoot, pNode); } return 0; } //创建二叉树:按照层次由root节点开始,一层层创建,借用queue实现 int createByLevel(std::vector<int> vecData) { if (vecData.empty()) { return -1; } std::queue<std::shared_ptr<Node>> que; std::vector<int>::iterator itor = vecData.begin(); if (m_pRoot == nullptr) { std::ostringstream ostrStream; ostrStream << *itor << std::endl; m_pRoot = std::make_shared<Node>(*itor, ostrStream.str()); itor++; } que.push(m_pRoot); while (itor != vecData.end()) { std::shared_ptr<Node> pNode = que.front(); //add node std::ostringstream ostrStream; ostrStream << *itor << std::endl; std::shared_ptr<Node> pNodeAdded = std::make_shared<Node>(*itor, ostrStream.str()); if (pNode->m_pLeftChild == nullptr) { pNode->m_pLeftChild = pNodeAdded; } else if (pNode->m_pRightChild == nullptr) { pNode->m_pRightChild = pNodeAdded; } //左右构建完成,出列,然后分别入列左右,分别再构建 if (pNode->m_pLeftChild != nullptr && pNode->m_pRightChild != nullptr) { que.pop(); que.push(pNode->m_pLeftChild); que.push(pNode->m_pRightChild); } itor++; } return 0; } //二叉树反转 int reversal(std::shared_ptr<Node> pTreeNodeStart) { if (pTreeNodeStart == nullptr) return 0; //reversal left tree reversal(pTreeNodeStart->m_pLeftChild); //reversal right tree reversal(pTreeNodeStart->m_pRightChild); //swap left child and right child std::swap(pTreeNodeStart->m_pLeftChild, pTreeNodeStart->m_pRightChild); return 0; } //判断二叉树是否对称 bool isMirror() { if (m_pRoot == nullptr) return true; else { //检查左右子树是否是镜像 return checkMirror(m_pRoot->m_pLeftChild,m_pRoot->m_pRightChild); } } bool checkMirror(std::shared_ptr<Node> leftChild, std::shared_ptr<Node> rightChild) { //两边都是null,ture if (leftChild == nullptr && rightChild == nullptr) return true; //两边只有一边是null,false if(leftChild == nullptr || rightChild == nullptr) return false; //两边都不是null if (leftChild->getData() != rightChild->getData()) return false; //检查左子的左边和右子的右边 bool ret1 = checkMirror(leftChild->m_pLeftChild, rightChild->m_pRightChild); //检查左子的右边和右子的左边 bool ret2 = checkMirror(leftChild->m_pRightChild, rightChild->m_pLeftChild); //同时都满足,才是ture return (ret1 && ret2); } //前序遍历: root->left->right int preorderDump(std::vector<int> &vecData) { return preorderTraversal(m_pRoot,vecData); } //中序遍历: left->root->right int inorderDump(std::vector<int> &vecData) { return inorderTraversal(m_pRoot, vecData); } //后序遍历: left->right->root int postorderDump(std::vector<int> &vecData) { return postorderTraversal(m_pRoot, vecData); } //按层遍历: root层--->叶子节点层 int levelDump(std::vector<int> &vecData) { return levelTraversal(m_pRoot, vecData); } std::shared_ptr<Node> root() { return m_pRoot; } private: //节点加入左子,还是右子的条件: 比较大小 //传入引用,改变pTreeNodeStartAdd的值 int addNode(std::shared_ptr<Node> &pTreeNodeStartAdd, std::shared_ptr<Node> pNode) { if (pTreeNodeStartAdd == nullptr) { pTreeNodeStartAdd = pNode; return 0; } //小于往左子树加入 if (pNode->getData() < pTreeNodeStartAdd->getData()) { addNode(pTreeNodeStartAdd->m_pLeftChild, pNode); } else //大于等于往右 { addNode(pTreeNodeStartAdd->m_pRightChild, pNode); } return 0; } //前序遍历,节点放入vector int preorderTraversal(std::shared_ptr<Node> pTreeNodeStart, std::vector<int> &vecData) { if (pTreeNodeStart == nullptr) { return 0; } //root vecData.push_back(pTreeNodeStart->getData()); //left preorderTraversal(pTreeNodeStart->m_pLeftChild, vecData); //right preorderTraversal(pTreeNodeStart->m_pRightChild, vecData); return 0; } //中序遍历,节点放入vector int inorderTraversal(std::shared_ptr<Node> pTreeNodeStart, std::vector<int> &vecData) { if (pTreeNodeStart == nullptr) { return 0; } //left inorderTraversal(pTreeNodeStart->m_pLeftChild, vecData); //root vecData.push_back(pTreeNodeStart->getData()); //right inorderTraversal(pTreeNodeStart->m_pRightChild, vecData); return 0; } //后续遍历节点放入vector int postorderTraversal(std::shared_ptr<Node> pTreeNodeStart, std::vector<int> &vecData) { if (pTreeNodeStart == nullptr) { return 0; } //left postorderTraversal(pTreeNodeStart->m_pLeftChild, vecData); //right postorderTraversal(pTreeNodeStart->m_pRightChild, vecData); //root vecData.push_back(pTreeNodeStart->getData()); return 0; } //借用一个临时队列来实现 //从root开始,加入队列,先访问后,将root的左右节点分别加入队列, //然后从队列取出左节点,访问后,将左节点的左右子节点入队列,再取出之前入列的右节点,访问后,将右节点的左右字节点入队列 //此时队列里面就会有root左子的左右子节点,右子的左右子节点 //按照此循环下去,直到队列里面没有元素,即到叶子节点为止了。 int levelTraversal(std::shared_ptr<Node> pTreeNodeStart, std::vector<int> &vecData) { if (pTreeNodeStart == nullptr) { return 0; } std::queue<std::shared_ptr<Node>> que; que.push(pTreeNodeStart); while (!que.empty()) { std::shared_ptr<Node> pNode = que.front(); que.pop(); //访问元素 vecData.push_back(pNode->getData()); //左子节点入队列 if (pNode->m_pLeftChild != nullptr) que.push(pNode->m_pLeftChild); //右子节点入队列 if(pNode->m_pRightChild != nullptr) que.push(pNode->m_pRightChild); } return 0; } private: std::shared_ptr<Node> m_pRoot; };

    测试代码:

    int main()
    {
        //创建树,非镜像二叉树,先查看各种遍历结果,反转后,再查看
        std::vector<int> vecData = {100,80,120,70,90,110,130,65,75,85,95,105,115,125,135};
        for (auto index : vecData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //创建树
        BinaryTree tree;
        tree.create(vecData);
        //是否镜像
        std::cout << "Tree is mirror: " << tree.isMirror() << std::endl;
        //前序遍历
        std::vector<int> vecDumpData;
        tree.preorderDump(vecDumpData);
    
        std::cout << "preorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //中序遍历
        vecDumpData.clear();
        tree.inorderDump(vecDumpData);
        std::cout << "inorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //后续遍历
        vecDumpData.clear();
        tree.postorderDump(vecDumpData);
        std::cout << "postorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //层级遍历
        vecDumpData.clear();
        tree.levelDump(vecDumpData);
        std::cout << "level traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //二叉树反转
        std::cout << "##############after reversal################ " << std::endl;
        tree.reversal(tree.root());
        
        //反转后,前序遍历
        vecDumpData.clear();
        tree.preorderDump(vecDumpData);
    
        std::cout << "preorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //中序续遍历
        vecDumpData.clear();
        tree.inorderDump(vecDumpData);
        std::cout << "inorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //后续遍历
        vecDumpData.clear();
        tree.postorderDump(vecDumpData);
        std::cout << "postorder traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
        //层级遍历
        vecDumpData.clear();
        tree.levelDump(vecDumpData);
        std::cout << "level traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
    
    
    
        //按照层级创建镜像二叉树,反转后,各个遍历输出应该一致
        std::cout << "##############tree2 createByLevel################ " << std::endl;
        BinaryTree tree2;
        tree2.createByLevel(vecData);
        //层级遍历,查看是否成功
        vecDumpData.clear();
        tree2.levelDump(vecDumpData);
        std::cout << "tree2 level traversal: ";
        for (auto index : vecDumpData)
        {
            std::cout << index << ',';
        }
        std::cout << std::endl;
    
        //创建树,是否镜像判断
        std::cout << "#######mirror binary tree####" << std::endl;
        std::vector<int> vecData2 = {1,2,2,3,4,4,3,5,6,7,8,8,7,6,5};
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
    
        BinaryTree mirrorTree;
        mirrorTree.createByLevel(vecData2);
        std::cout << "Tree is mirror: " << mirrorTree.isMirror() << std::endl;
        //层级遍历,查看结果
        vecData2.clear();
        mirrorTree.levelDump(vecData2);
        std::cout << "mirrorTree level traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
        //前序遍历
        vecData2.clear();
        mirrorTree.preorderDump(vecData2);
        std::cout << "mirrorTree preorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
        //中序遍历
        vecData2.clear();
        mirrorTree.inorderDump(vecData2);
        std::cout << "mirrorTree inorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
        //后序遍历
        vecData2.clear();
        mirrorTree.postorderDump(vecData2);
        std::cout << "mirrorTree postorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
        //镜像二叉树反转后查看结果
        std::cout << "mirror binary tree reversal==============" << std::endl;
        mirrorTree.reversal(mirrorTree.root());
        vecData2.clear();
        mirrorTree.levelDump(vecData2);
        std::cout << "mirrorTree level traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
    
        vecData2.clear();
        mirrorTree.preorderDump(vecData2);
        std::cout << "mirrorTree preorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
    
        vecData2.clear();
        mirrorTree.inorderDump(vecData2);
        std::cout << "mirrorTree inorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
    
        vecData2.clear();
        mirrorTree.postorderDump(vecData2);
        std::cout << "mirrorTree postorder traversal: ";
        for (auto index : vecData2)
        {
            std::cout << index << ",";
        }
        std::cout << std::endl;
    
        return 0;
    }
    View Code

    输出:

    层序遍历,返回二维矩阵leetcode

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
           vector <vector <int>> ret;
            if(root == nullptr)
                return ret;
            
            std::queue<TreeNode*> que;
            que.push(root);
    
            while(!que.empty())
            {
                int size = que.size();
                //each level
                vector<int> row;
                for(int i = 0; i < size; i++)
                {
                    TreeNode *pNode = que.front();
                    row.push_back(pNode->val);
    
                    if(pNode->left != nullptr)
                        que.push(pNode->left);
                    if(pNode->right != nullptr)
                        que.push(pNode->right);
    
                    que.pop();
                }
                //
                ret.push_back(row);
            }
    
            return ret;
        }
    };

    非递归的前序和中序

    vector<int> inorderTraversal(TreeNode* root) {
            stack<TreeNode*> stackNode;
            vector<int> vectorNode;
            TreeNode* p = root;
            while(p != nullptr || !stackNode.empty())
            {
                while(p != nullptr){
                    //先访问左边,再出栈访问中和右,前序
                    //vectorNode.push_back(p->val);
                    ////
                    stackNode.push(p);
                    p = p->left;
                }
                p = stackNode.top();
                //最左边先出栈访问,中序遍历
                vectorNode.push_back(p->val);
                p = p->right;
                stackNode.pop();
            }
            return vectorNode;        
        }
    

      

  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/leehm/p/12929130.html
Copyright © 2011-2022 走看看