二叉树类: 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; }
输出:
层序遍历,返回二维矩阵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; }