3.2 叶子节点个数
代码1:
1. void BTreeLeafSize(BTNode* root, int* pcount) 2. { 3. if (root == NULL) 4. { 5. return; 6. } 7. if ((root->left == NULL) && (root->right == NULL)) 8. { 9. (*pcount)++; 10. } 11. BTreeLeafSize(root->left, pcount); 12. BTreeLeafSize(root->right, pcount); 13. }
1. int main() 2. { 3. int count = 0; 4. BTreeLeafSize(tree, &count); 5. printf("%d\n", count); 6. return 0; 7. }
思路1:遍历+计数【代码1】
代码2:
1. int BTreeLeafSize(BTNode* root) 2. { 3. if (root == NULL) 4. { 5. return 0; 6. } 7. if (root->right == NULL && root->left == NULL) 8. { 9. return 1; 10. } 11. return BTreeLeafSize(root->right) + BTreeLeafSize(root->left); 12. }
1. int main() 2. { 3. BTreeLeafSize(tree); 4. printf("%d\n", BTreeLeafSize(tree)); 5. return 0; 6. }
思路2:分治【代码2】
数的叶子节点等于左子树的叶子节点+右子树的叶子节点。一直分到这个小树的根的节点不等于NULL,但是左右子树为NULL。
3.3 第k层节点个数
1. int BTreeKLevelSize(BTNode* root, int k) 2. { 3. assert(k >= 1); 4. if (root == NULL) 5. { 6. return 0; 7. } 8. if (k == 1) 9. { 10. return 1; 11. } 12. return BTreeKLevelSize(root->left, k - 1) + BTreeKLevelSize(root->right, k - 1); 13. }
分治思想:(1)空树,返回0(2)非空,且k==1,返回1(3)非空且K>1,装换成左子树K-1层节点个数+右子树k-1层节点个数。
即:【首先,求第k层节点个数,首先这一层看成满的,如果有节点就返回1,如果没有节点就返回0】其次(1)如果求的是第一层的节点个数,那就直接是1,(2)如果求的是第二层的节点个数,那么可以转化成求左子树的第一层节点个数+右子树的第一层节点个数(3)如果求的是根的第三层的节点个数,那么可以转化成求该根左子树的第二层节点个数+右子树的第二层节点个数,再转化成该根的左子树的左子树的第一层节点个数+该根左子树的右子树的第一层节点个数+根的右子树的左子树的第一层节点个数+该根右子树的右子树的第一层节点个数【第一层(1)空树,返回0(2)k==1,返回1】
3.4 二叉树的高度/深度
1. int BTreeDepth(BTNode* root) 2. { 3. if (root == NULL) 4. { 5. return 0; 6. } 7. return BTreeDepth(root->left) > BTreeDepth(root->right) ? (BTreeDepth(root->left) + 1) : (BTreeDepth(root->right) + 1); 8. }
分治思想:左子树和右子树高度较大的那一个+1.
3.5 查找值为x的节点
1. BTNode* BTreeFind(BTNode* root, BTDataType x) 2. { 3. if (root == NULL) 4. { 5. return NULL; 6. } 7. if (root->data == x) 8. { 9. return root; 10. } 11. BTNode* ret1 = BTreeFind(root->left, x); 12. if (ret1) 13. { 14. return ret1; 15. } 16. BTNode* ret2 = BTreeFind(root->right, x); 17. if (ret2) 18. { 19. return ret2; 20. } 21. return NULL; 22. }
分治思想:【如果左子树找到了,那么右子树就不需要再进行查找】
找到了指针,就可以对其进行改变值
四、二叉树的创建和销毁
4.1 构建二叉树
链接:牛客
代码:
1. #include <stdio.h> 2. #include <stdlib.h> 3. typedef struct BinaryTreeNode 4. { 5. char data; 6. struct BinaryTreeNode* left; 7. struct BinaryTreeNode* right; 8. }BTNode; 9. //先构建一个二叉树【前序遍历】 10. BTNode* CreatTree(char* a, int* pi) 11. { 12. if (a[*pi] == '#') 13. { 14. (*pi)++; 15. return NULL; 16. } 17. //先构建根 18. BTNode* root = (BTNode*)malloc(sizeof(BTNode)); 19. root->data = a[*pi]; 20. (*pi)++; 21. //再构建左子树和右子树 22. root->left = CreatTree(a, pi); 23. root->right = CreatTree(a, pi); 24. return root; 25. } 26. 27. void InOrder(BTNode* root) 28. { 29. if (root == NULL) 30. { 31. return; 32. } 33. InOrder(root->left); 34. printf("%c ", root->data); 35. InOrder(root->right); 36. } 37. 38. int main() 39. { 40. char a[100]; 41. scanf("%s", a); 42. int i = 0; 43. BTNode* tree = CreatTree(a, &i); 44. InOrder(tree); 45. free(tree); 46. tree = NULL; 47. return 0; 48. }
思想:先序遍历的思想的字符串,建立二叉树【遇到'#',就返回NULL】,然后再中序遍历的思想进行打印。
4.2 二叉树销毁
1. void BTreeDestory(BTNode* root) 2. { 3. if (root == NULL) 4. { 5. return; 6. } 7. BTreeDestory(root->left); 8. BTreeDestory(root->right); 9. free(root); 10. } 11. int main() 12. { 13. BTNode* tree = CreatBinaryTree(); 14. BTreeDestory(tree);//想改变谁的内容,就需要把谁的地址传递给函数。 15. free(tree); 16. tree = NULL; 17. return 0; 18. }
(1)后序遍历(2)一级指针,tree需要在函数外面进行销毁。(3)如果传递的是二级指针,就可以在函数内进行销毁。
4.3 判断二叉树是否为完全二叉树
1. bool BinaryTreeComplete(BTNode* root) 2. { 3. Queue q; 4. QueueInit(&q); 5. if (root) 6. { 7. QueuePush(&q, root); 8. } 9. while (!QueueEmpty(&q)) 10. { 11. BTNode* front = QueueFront(&q); 12. if (front == NULL) 13. { 14. break; 15. } 16. QueuePop(&q); 17. QueuePush(&q, root->left);//不管是还是不是NULL,都进入队列 18. QueuePush(&q, root->right); 19. } 20. while (!QueueEmpty(&q)) 21. { 22. BTNode* front = QueueFront(&q); 23. if (front != NULL) 24. { 25. QueueDestory(&q); 26. return false; 27. } 28. QueuePop(&q); 29. } 30. QueueDestory(&q); 31. return true; 32. }
思想:层序遍历的思想;一个节点出队列的时候,会把该节点下一层的节点入队列(把NULL也进入队列),完全二叉树,层序遍历完之后,就不会出现NULL。如果不是完全二叉树,就会出现NULL。
思路:(1)层序遍历,空节点也可以进队列(2)出到空节点以后,出队列中所有数据,如果全是NULL,就是完全二叉树,如果有非空,就不是完全二叉树。
注意:返回数据之前,要把队列给销毁【否则会出现内存泄漏】