二叉树的建立、释放内存、层序遍历输出
leetcode的输入案例其实是数组存储方式,这样建树很方便
对于上面这个案例,你可以发现,输入其实层序遍历存储在数组,这样的结果是很好建树,利用二叉树在数组中的相对关系,如下图
数据结构定义:
// Definition for a TreeNode.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
1 数组存储建树
原输入中null表示空结点,这里改成-1,主要是更加好表示,否则用字符串存储,增加复杂度,也没多大意义。
数组开始下标是0,所以下面都加1,所以直接用递归的先序建树,很方便
/** \brief creatList 数组建树
* \author xxx
* \copyright GNU Public License
* \version 1.0
* \date 2020-1-15
*
* \param[in] s 输入数组
* \param[in] i 必须为0
* \return 返回树的根节点
*/
TreeNode* creatTree(std::vector<int> nums, int i){
if(i >= nums.size() || nums[i] == -1) /**<出现无效下标 或者值为1均返回nullptr */
return nullptr;
TreeNode *root = new TreeNode(nums[i]); /**<创建根节点 */
root->left = creatTree(nums, 2*i+1); /**<创建左子树 */
root->right = creatTree(nums, 2*i+2); /**<创建右子树 */
return root;
}
下面是一个案例
2 二叉树释放内存
使用new分配的内存,需要手动释放,这是必须的,不要忘记。
注意,释放从下往上,用后序遍历方式释放!
代码已经用valgrind
,没有内存泄漏!!!,你也可以自己测试下
/** \brief freeTree 释放内存
* \author xxx
* \copyright GNU Public License
* \version 1.0
* \date 2020-1-15
* \remark Valgrind已经通过测试,没有内存泄漏
* \remark valgrind --tool=memcheck --leak-check=full ./_1
*
* \param[in] root 输入二叉树根节点
* \return void
*/
void freeTree(TreeNode* root) {
if(root == nullptr)
return;
freeTree(root->left);
freeTree(root->right);
delete root;
}
一个输出
➜ tree git:(master) ✗ valgrind --tool=memcheck --leak-check=full ./_1
==6079== Memcheck, a memory error detector
==6079== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6079== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6079== Command: ./_1
==6079==
==6079== error calling PR_SET_PTRACER, vgdb might block
3
==6079==
==6079== HEAP SUMMARY:
==6079== in use at exit: 0 bytes in 0 blocks
==6079== total heap usage: 21 allocs, 21 frees, 74,760 bytes allocated
==6079==
==6079== All heap blocks were freed -- no leaks are possible
==6079==
==6079== For counts of detected and suppressed errors, rerun with: -v
==6079== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
3 二叉树遍历
遍历我选择了层序遍历,这样的输出结果,可以很容易分辨是否正确或者错误
/** \brief printTree 层序打印二叉树
* \author xxx
* \copyright GNU Public License
* \version 1.0
* \date 2020-1-16
*
* \param[in] root 输入二叉树根节点
* \return void
*/
void printTree(TreeNode* root) {
if(root == nullptr)
return;
std::queue<TreeNode*> Q;
Q.push(root);
while (!Q.empty()) {
TreeNode *node = Q.front(); Q.pop();
std::cout << node->val << " ";
if (node->left) Q.push(node->left);
if(node->right) Q.push(node->right);
}
}
4 测试案例
std::vector<int> nums = {3, 9, 20, -1, -1, 15, 7};
TreeNode *tree = creatTree(nums, 0);
/**<do something */
printTree(tree);
freeTree(tree);