数据结构7:基本的二叉树遍历及题目

一般我们在学习数据结构的时候都会实现它最基本的增删查改方式,但是二叉树这个数据结构不太一般,增删查改没有什么意义,由于二叉树的相关遍历涉及到递归,我们先不学习创建二叉树,而是从遍历开始

简单的创建一个二叉树并不难,创建几个节点然后当作二叉树连起来即可:

typedef  int   BTDataType;


typedef struct BTNode
{
	BTDataType data;
	struct BTNode* left;
	struct BTNode* right;
}BT;


BT* CreatTree()
{
	BT* n1 = (BT*)malloc(sizeof(BT));
	assert(n1);
	BT* n2 = (BT*)malloc(sizeof(BT));
	assert(n2);
	BT* n3 = (BT*)malloc(sizeof(BT));
	assert(n3);
	BT* n4 = (BT*)malloc(sizeof(BT));
	assert(n4);
	BT* n5 = (BT*)malloc(sizeof(BT));
	assert(n5);
	BT* n6 = (BT*)malloc(sizeof(BT));
	assert(n6);

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;


	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	return n1;
}

 逻辑结构如下图:

 

二叉树的遍历:

前序遍历:

void preOrder(BT* root)
{

	if (root == NULL)
	{
		printf("NULL ");
		return;
	}


	printf("%d ", root->data);
	preOrder(root->left);
	preOrder(root->right);
}

中序遍历:

void MidOrder(BT* root)
{

	if (root == NULL)
	{
		printf("NULL ");
		return;
	}


	preOrder(root->left);
	printf("%d ", root->data);

	preOrder(root->right);
}

后序遍历:

//后序遍历
void leftOrder(BT* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}


	preOrder(root->left);
	preOrder(root->right);
	printf("%d ", root->data);

}

二叉树功能实现:

 二叉树节点个数:

int TreeSize(BT* root)
{
	if (root == NULL)
		return 0;

	return TreeSize(root->left) + TreeSize(root->right) + 1;
}

二叉树叶子节点个数:

int BinaryTreeLeafSize(BT* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;

	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

二叉树高度:

int BinaryTreeLeafHeight(BT* root)
{
	if (root == NULL)
		return 0;

	int left = BinaryTreeLeafHeight(root->left) + 1;
	int right = BinaryTreeLeafHeight(root->right) + 1;

	if (left > right)
		return left;
	else
		return right;

}

二叉树第k层节点个数:

int BinaryTreeLevelKSize(BT* root, int k)
{
	assert(k > 0);
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;

	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);


}

 二叉树查找值为x的节点:

BT* BinaryTreeFind(BT* root, BTDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	BT* leftret = BinaryTreeFind(root->left, x);

	if (leftret)
		return leftret;

	BT* rightret  = BinaryTreeFind(root->right, x);

	if (rightret)
		return rightret;
	return NULL;

}

 一些有关二叉树的题目

相信不少的读者在第一次接触到二叉树的时候对递归的把握并不深刻,在这里,其实递归的本质就是抛去了我们平常写代码注重全局的思想,改成了注重每次递归的时候应该做的事情,我个人没法详细表述的很好,在这里推荐一篇文章:三道题套路解决递归问题 | lyl's blog

单值二叉树:

链接:力扣

 


        if(root== NULL)
        return true;


        if(root->left && root->val != root -> left ->val )
        return false;
        if(root->right && root->val != root ->right -> val)
        return false;

        bool lefret = isUnivalTree(root ->left);
        bool rightret = isUnivalTree(root ->right);


        return lefret && rightret;

 同遍历整个二叉树查找某个值的逻辑相同。

翻转二叉树:

链接:力扣

思路:面对递归类型的题目,不应该直接专注于解决一整颗树上,而是每一步应该做什么,这题的主体每步的逻辑就是置换左右子树,那么我们不需要多想,直接交换左右子树,剩下的交给递归处理,不需要过度的照顾全局。

扫描二维码关注公众号,回复: 16002771 查看本文章

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {

        if(root == NULL)
        return NULL;

        struct TreeNode* tmp = root->left;
        root -> left = root->right;

        invertTree(root->left);
        invertTree(root->right);

        return root;

    }
};

 相同的树:

链接:力扣

思路:同上的翻转相同,我们只需要关注每一个节点对比的值是否符合要求即可,剩下的交给递归

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;


    bool leftret = isSameTree(p->left,q->left);
    bool rightret = isSameTree(p->right,q->right);


    return leftret && rightret ;


}

层序遍历:

由于递归的栈帧消耗还是比较大的,所以用非递归的方法来遍历二叉树还是非常有必要的,借助队列的先进先出的特性可以很好的实现非递归遍历。

思路:二叉树无非就是跟和左子树右子树的问题,逻辑上来说,在我们在到达一个节点的时候接下来就是得到它的值或者是左子树右子树,那么我们就只需要先将根节点入队列,再将根的左子树右子树入队列,把根出队列后,再把其左右子树视作新根,再拆开成为左右子树,以达到层序遍历的效果。

void BinaryTreeLevelOrder(BTNode* root)// 层序遍历
{
	Queue q;
	QueueInit(&q);
	if (root)//root不为空,放数据
		QueuePush(&q,root);
 
	while (!QueueEmpty(&q))//如果队列不为空,则循环
	{
		BTNode* front = QueueFront(&q);//拿队头数据
		printf("%d ", front->data);
		QueuePop(&q);
		if (front->left)
			QueuePush(&q, front->left);
 
		if (front->right)
			QueuePush(&q, front->right);
	}
 
	QueueDestroy(&q);
}

猜你喜欢

转载自blog.csdn.net/m0_53607711/article/details/128331361