C语言学习之二叉树(有例题)

简介

二叉树是一种重要的数据结构,每个节点最多有两个字节点,分为左右节点,

二叉树构建和相关函数

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;
}

先构建一颗二叉树,再中序遍历,
如果字符串字符符合题意,创建一个节点,字符串因为先序遍历,先让节点加入树,再让左右子树继续建立

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值