数据结构:二叉树OJ
本章代码见:https://gitee.com/jxxx404/c-language-learning/commit/ee0d62a406708562f83cb9ebeda8dbfc54ed356d
本章需要的知识:
https://blog.csdn.net/2401_86123468/article/details/151797148?spm=1001.2014.3001.5501
https://blog.csdn.net/2401_86123468/article/details/151366890?spm=1001.2014.3001.5501
1.二叉树选择题
二叉树性质:
(1)对任何一棵二叉树,如果度为0,其叶结点个数为n0,度为2的分支结点个数为n2,则有n0 = n2 + 1。
证明:
边数 = 结点个数 - 1,二叉树的结点只有三种情况:度为0,1,2。
由此可得:边数 = n0 + n1 + n2 - 1
又因为,度为2的结点有:两条边;度为1的结点有:一条边;度为0的结点有:零条边。
因此,又可得:边数 = 2n2 + n1
所以:n0 = n2 + 1
1.1依据此性质,完成下列题目:
1.1.1
1. 某⼆叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该⼆叉树中的叶⼦结点数为( )
A 不存在这样的⼆叉树
B 200
C 198
D 199
由于题中求叶子结点,及求n0的大小,则n0 = n2 + 1 = 199 + 1 = 200
所以选A。
1.1.2
2.在具有 2n 个结点的完全⼆叉树中,叶⼦结点个数为( )
A n
B n+1
C n-1
D n/2
由题可得:n0 + n1 + n2 = 2n,n0 = n2 + 1 => 2n0 = 2n - n1 + 1 ,由于n1取值有0或1两种可能,所以,可得结果:n0 = n或n0 = n + 1/2
所以选A。
1.1.3
3.⼀棵完全⼆叉树的结点数位为531个,那么这棵树的⾼度为( )
A 11
B 10
C 8
D 12
由题得:n = 531,二叉树与结点数的关系:n = 2^h - 1 => h = log (n + 1),因为2^10 = 1024,2^9 = 512,所以这颗二叉树前9层总共有512 - 1 = 511个结点,第九层有2^(9 -1) 个结点。
所以选B。
1.1.4
4.⼀个具有767个结点的完全⼆叉树,其叶⼦结点个数为()
A 383
B 384
C 385
D 386
由题得:n0 + n1 + n2 = 767,n0 = n2 + 1 => 2n0 = 767 - n1 -1,由于n1取值有0或1两种可能,所以,可得结果:2n0 = 768或 2n0 = 767
所以选B。
1.2链式二叉树遍历选择题
1.2.1
1.某完全⼆叉树按层次输出(同⼀层从左到右)的序列为 ABCDEFGH 。该完全⼆叉树的前序序列为(
)
A ABDHECFG
B ABCDEFGH
C HDBEAFCG
D HDEBFGCA
画出按层次排序的二叉树:
所以选A。
1.2.2
2.⼆叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则⼆叉树根结点为()
A E
B F
C G
D H
由先序遍历可直接得,选A。
1.2.3
3.设⼀课⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为____。
A adbce
B decab
C debac
D abcde
由后序遍历可得根节点为A,再以中序遍历得左节点B,再根据后序遍历得根节点,以此类推。
最终选D。
1.2.4
4.某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右)的
序列为
A FEDCBA
B CBAFED
C DEFCBA
D ABCDEF
根据1.2.3的做法,得:
2.二叉树算法题
2.1单值二叉树
https://leetcode.cn/problems/univalued-binary-tree/description/
理解题意:
思路:使用递归,以root为空作为限制条件,如果root非空,依次遍历root与其左右孩子结点的值并比较。
bool isUnivalTree(struct TreeNode* root) {if (root == NULL) {return true;}// root非空,root跟左右孩子节点的值进行比较if (root->left && root->left->val != root->val) {return false;}if (root->right && root->right->val != root->val) {return false;}return isUnivalTree(root->left) && isUnivalTree(root->right);
}
2.2相同的树
https://leetcode.cn/problems/same-tree/description/
理解题意:
思路:使用递归,分别遍历两个二叉树的左右子树并依次比较值,直至叶子结点返回NULL。
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if(p == NULL && q == NULL){return true;}//其中一个为空if(p == NULL || q == NULL){return false;}//都不为空if(p->val != q->val){return false;}return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
2.3对称二叉树
https://leetcode.cn/problems/symmetric-tree/description/
理解题意:
思路:使用递归,以叶子结点为NULL作为限制条件,再分别对二叉树的左右子树的左节点和右节点进行值比较。
typedef struct TreeNode TreeNode;
bool isSymmeTree(TreeNode* p, TreeNode* q)
{if(p == NULL && q == NULL){return true;}if(p == NULL || q == NULL){return false;}if(p->val != q->val){return false;}return isSymmeTree(p->left,q->right) && isSymmeTree(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root) {return isSymmeTree(root->left,root->right);
}
2.4另一棵树的子树
https://leetcode.cn/problems/subtree-of-another-tree/description/
思路:同上两道题,都先判断两二叉树是否相同,再遍历root和subRoot并分别判断两二叉树中是否有相同的树,最后将root的左右子树分别与subRoot作比较,并返回。
typedef struct TreeNode TreeNode;
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if(p == NULL && q == NULL){return true;}//其中一个为空if(p == NULL || q == NULL){return false;}//都不为空if(p->val != q->val){return false;}return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {if(root == NULL){return false;}if(isSameTree(root,subRoot)){return true;}return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}
2.5二叉树遍历
2.5.1二叉树前序遍历
https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
理解题意:
思路:求得二叉树结点个数,再写上两章节实现过的前序遍历的代码,注意题中给的函数参数还有返回数组的大小,并且提示要自己malloc。
typedef struct TreeNode TreeNode;
int BinaryTreeSize(TreeNode* root)
{if(root == NULL){return 0;}return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
void preOrder(TreeNode* root, int* arr, int* i)
{if(root == NULL){return;}arr[(*i)++] = root->val;preOrder(root->left,arr,i);preOrder(root->right,arr,i);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {//二叉树结点个数* returnSize*returnSize = BinaryTreeSize(root);int* arr = (int*)malloc(sizeof(int)*(*returnSize));//前序遍历int i = 0;preOrder(root,arr,&i);return arr;
}
2.5.2二叉树中序遍历
https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
理解题意:
思路:同上。
typedef struct TreeNode TreeNode;
int BinaryTreeSize(TreeNode* root)
{if(root == NULL){return 0;}return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
void inorder(TreeNode* root, int* arr, int* i)
{if(root == NULL){return;}inorder(root->left,arr,i);arr[(*i)++] = root->val;inorder(root->right,arr,i);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = BinaryTreeSize(root);int* arr = (int*)malloc(sizeof(int)*(*returnSize));//int i = 0;inorder(root,arr,&i);return arr;
}
2.5.3二叉树后序遍历
https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
思路与做法基本同上。
2.6二叉树的构建与遍历
https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef
理解题意:
思路:根据先序遍历的字符串,以#为空格为基础,建立二叉树,再通过中序遍历输出遍历结果。
注意:此网站为牛客网,需要自己书写头文件以及主函数等。
#include <stdio.h>
#include <stdlib.h>//定义二叉树结构
typedef struct BinaryTreeNode{char data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;BTNode* buynode(char ch)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));newnode->data = ch;newnode->left = newnode->right = NULL;return newnode;
}
//创建二叉树
BTNode* createTree(char* arr, int* i)
{if(arr[*i] == '#'){(*i)++;return NULL;}BTNode* root = buynode(arr[(*i)++]);root->left = createTree(arr, i);root->right = createTree(arr, i);return root;
}
//中序
void InOrder(BTNode* root)
{if(root == NULL){return;}InOrder(root->left);printf("%c ",root->data);InOrder(root->right);
}
int main() {//读取输入的字符串,保存在数组中char arr[100];scanf("%s",arr);int i= 0;BTNode* root = createTree(arr, &i);InOrder(root);return 0;
}
本章完。