1.二叉树的销毁 (后序)
思路:
有点三过家门而不入 的感觉。
代码:
// 二叉树销毁
void TreeDestroy(BTNode* root)
{
if (root == NULL)
{
return;
}
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
//root = NULL
}
root用不用置空要考虑 形参的改变不会影响实参
2.二叉树节点个数
思路:
分治思想
代码:
int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
3.二叉树叶子节点个数
思路:
和找节点个数思路相似,但是些限定条件,要根左子树右子树都为空才能返回1。后边也是左子树和右子树相加返回根
代码:
//叶子结点个数
int TreeLeafSize(BTNode* root)
{
//空返回 0
if (root == NULL)
{
return 0;
}
//叶子返回 1
if (root->left == NULL && root->right == NULL)
{
return 1;
}
//左子树+右子树
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
4.二叉树第k层节点个数
思路:
代码:
int TreeKLevel(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return TreeKLevel(root->left, k - 1)
+ TreeKLevel(root->right, k - 1);
}
5.二叉树中查找值为x的节点 (前序)
思路:
代码:
BTNode* TreeFind(BTNode* root, int x)
{
if (root == NULL)
{
return NULL;
}
if (root->val = x)
{
return root->val;
}
//先定义一个返回值
BTNode* ret = NULL;
//开始递归左子树和右子树
ret = TreeFind(root->left, x);
if (ret)
{
return ret;
}
ret = TreeFind(root->right, x);
if (ret)
{
return ret;
}
return NULL;
}
6.二叉树的前序遍历(中序和后序遍历思想是一样的)
思路:
代码:
//前序遍历
void PrevOder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->val);
PrevOder(root->left);
PrevOder(root->right);
}
//中序和后序就是调换一下printf的位置
7.层序遍历
思路:
代码:
//层序遍历
void LevelOrder(BTNode* root)
{
Que q;
QueueInit(&q);
//根不为空把根入进去
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
//取队头节点,先进先出
BTNode* front = QueueFront(&q);
printf("%d", front->val);
//把左右孩子入进去再出来,空不进去。根出去的时候左右子树也要入队
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
ps:会用到列表的知识,因为不是重点所以代码没写 。
有些注意事项:.h会被展开,所以放在下面,它会向上找。用树节点的指针
8.判断二叉树是不是完全二叉树
思路:
代码:
//判断二叉树是否是完全二叉树
int TreeComplete(BTNode* root)
{
Que q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
if (front == NULL)
{
break;
}
QueuePush(&q, front->left);
QueuePush(&q, front->right);
QueuePop(&q);
}
//已经遇到空节点,如果队列中后面的节点还有非空,就不是完全二叉树
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
9.通过前序遍历的二叉树的数组"ABD##E#H##CF##G##"构建二叉树
思路:
代码:
BTNode* CreateTree(BTDataType* a, int n, int* pi)
{
if (a[*pi] == '#')
{
(*pi)++;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode)*n);
root->val = a[*pi];
(*pi)++;
root->left = CreateTree(a, n, pi);
root->right = CreateTree(a, n, pi);
return root;
}
这段代码主要作用是在于理解。
总结:
理解困难就画递归展开图理解,但是要慢慢的能在树上画图理解。如果是理解了写不出来就多练多思考。多花点时间去消化,找一些题目做做,后边的学习都是以前边的为基础。
《杂谈随想录》:
之前有人告诉我60分更重要,硅谷有句名言叫move fast and break things,意思是说要快速的行动,即便事情会被搞砸。每个人每天都有很多事情要执行,但是执行起来很慢,因为感觉自己所具备的条件不够完美或者计划还不够周全,就会担心失败担心做不到100分,所以迟迟都不会行动。我之前每次做一件事情之前都喜欢暗示自己要尽可能做到完美,这样最大的影响就是给自己不必要的压力,让自己迟迟不能开始行动,其实100分根本不重要,60分才重要,因为60分至少让你有了开始行动的动力,做一件100分事情的精力,可以帮你完成很多件60分的事情。
之前我不是很理解,现在想他当时想表达给我的意思是,不要还没做就想着一定要做到100分,而是冒着即使60分也要开始的心态,在开始以后再不断调试的做到更好。