文章目录
简介
二叉树是一种重要的数据结构,每个节点最多有两个字节点,分为左右节点,
二叉树构建和相关函数
typedef struct binarytree
{
int val;
struct binarytree* left;
struct binarytree* right;
}BTNode;
BTNode* Buytree(int x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
perror("malloc fail");
return NULL;
}
node->val = x;
node->left = NULL;
node->right = NULL;
return node;
}
函数Buytree创建的是一个节点
BTNode* CreateTree()
{
BTNode* node1 = Buytree(1);
BTNode* node2 = Buytree(2);
BTNode* node3 = Buytree(3);
BTNode* node4 = Buytree(4);
BTNode* node5 = Buytree(5);
BTNode* node6 = Buytree(6);
BTNode* node7 = Buytree(7);
node1->left = node2;
node1->right = node3;
node2->left = node4;
node2->right = node5;
node3->left = node6;
node6->left = node7;
return node1;
}
该函数把一个个节点连接起来,创建成一颗树。
//int treesize(BTNode* root)
//{
// if (root == NULL)
// return 0;
// else return treesize(root->left) + treesize(root->right) + 1;
//}
void treesize(BTNode* root,int* psize)
{
if (root==NULL)
return;
++(*psize);
treesize(root->left,psize);
treesize(root->right,psize);
}
求二叉树节点数量,第一种分治,第二种遍历,
第一种,可理解老大的事分给小弟做,一层层往下发。求一共多少人,老大只需要知道两个小弟分别带多少人,再加上他自己就行。 小弟再统计小弟的小弟,如果遇到空节点就返回0;
第二种,遍历整个二叉树,遇到一个节点就加一次,
int treelevel(BTNode* root,int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return treelevel(root->left, k - 1) + treelevel(root->right,k-1);
}
求一颗二叉树某一层的节点个数,也是分治思想,
比如k=4,从第一层节点视角求第四层,就相当于第二层视角的第三层,第三层视角的第一层,
再返回第三层每个节点的左右节点个数,再一步步返回就知道某一层的个数了。
int treeheight(BTNode* root)
{
if (root == NULL)
return 0;
int left = treeheight(root->left) + 1;
int right = treeheight(root->right) + 1;
if (left >= right)
return left;
else return right;
}
求树的高度,依旧分治思想,
用变量把左右子树高度存起来,返回更高的那一颗,再加上自己的1。
void Preorder(BTNode* root)
{
if (root == NULL)
{
/*perror("fail");*/
return;
}
printf("%d", root->val);
Preorder(root->left);
Preorder(root->right);
}
void Inorder(BTNode* root)
{
if (root == NULL)
{
/*perror("fail");*/
return;
}
Inorder(root->left);
printf("%d", root->val);
Inorder(root->right);
}
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
前序遍历,优先根再左再右,
中序遍历,先左再中再右,
后续,先左再右再根,
BTNode* treefind(BTNode* root, int x)
{
if (root == NULL)
return NULL;
if (root->val == x)
return root;
BTNode* l = treefind(root->left, x);
if (l)
return l;
BTNode* r = treefind(root->right, x);
if (r)
return r;
return NULL;
}
查找某个数,返回那个节点的地址,**这代表既可以查找某个数是否存在,又可以修改那个节点**;
int main()
{
BTNode* root = CreateTree();
int psize = 0;
//printf("%d",treesize(root);
treesize(root, &psize);
printf("%d", psize);
printf("%d",treelevel(root, 3));
printf("%d",treeheight(root));
printf("\n");
Preorder(root);
printf("\n");
BTNode* t=treefind(root, 5);
printf("%d", t->val);
return 0;
}
测试代码;
单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true;否则返回 false。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isUnivalTree(struct TreeNode* root) {
if(root==NULL)
return true;
if(root->left)
{
if(root->val!=root->left->val)
return false;
}
if(root->right)
{
if(root->val!=root->right->val)
return false;
}
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
判断父节点与左右节点是否相同,不相同直接返回0;
因为涉及子节点的引用,因此要先判断是否是空节点,
返回父节点的子节点,让他们继续向下判断;
相同的树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if(q==NULL&&p==NULL)
return true;
if(q==NULL||p==NULL)
return false;
if(p->val!=q->val)
return false;
if(!isSameTree(p->left,q->left)||!isSameTree(p->right,q->right))
return false;
return true;
}
判断俩树是否相同,判断对应节点是否相同,共3种情况,
两空
一空一有
两有
如果相同就向下判断,无错误就返回真;
另一颗树的子树
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if(q==NULL&&p==NULL)
return true;
if(q==NULL||p==NULL)
return false;
if(p->val!=q->val)
return false;
if(!isSameTree(p->left,q->left)||!isSameTree(p->right,q->right))
return false;
return true;
}
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);
}
遍历大树,用每一个节点判断是否是相同的子树,
二叉树遍历
描述
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
输入描述:
输入包括1行字符串,长度不超过100。
输出描述:
可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。
示例1
输入:
abc##de#g##f###
输出:
c b e g d f a
#include <stdio.h>
struct tree{
char val;
struct tree* left;
struct tree* right;
};
struct tree* create(char* s,int* i)
{
if(s[*i]=='#')
{
(*i)++;
return NULL;
}
struct tree* root=(struct tree*)malloc(sizeof(struct tree));
root->val=s[(*i)++];
root->left=create(s,i);
root->right=create(s,i);
return root;
}
void inorder(struct tree* root)
{
if(root==NULL)
return;
inorder(root->left);
printf("%c ",root->val);
inorder(root->right);
}
int main() {
char s[100];
while(scanf("%s",s)!=EOF)
{
int i=0;
struct tree* root=create(s,&i);
inorder(root);
}
return 0;
}
先构建一颗二叉树,再中序遍历,
如果字符串字符符合题意,创建一个节点,字符串因为先序遍历,先让节点加入树,再让左右子树继续建立