Data structure 7: Basic binary tree traversal and topics

Generally, when we learn the data structure, we will implement its most basic method of adding, deleting, checking and modifying, but the data structure of the binary tree is not very general. , but start by traversing

It is not difficult to simply create a binary tree, just create a few nodes and connect them as a binary tree:

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

 The logical structure is as follows:

 

Traversal of a binary tree:

Preorder traversal:

void preOrder(BT* root)
{

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


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

Inorder traversal:

void MidOrder(BT* root)
{

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


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

	preOrder(root->right);
}

Postorder traversal:

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


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

}

Binary tree function implementation:

 The number of binary tree nodes:

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

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

The number of leaf nodes in the binary tree:

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

Binary tree height:

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;

}

The number of nodes in the kth layer of the binary tree:

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


}

 Find a node with value x in a binary tree:

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;

}

 Some topics about binary trees

I believe that many readers do not have a deep grasp of recursion when they first come into contact with binary trees. Here, in fact, the essence of recursion is to throw away our usual thinking of writing code and focus on the overall situation, and change it to focus on each recursion. What should be done at the time, I personally can't express it in detail, I recommend an article here: Three-question routines to solve recursive problems | lyl's blog

Single-valued binary tree:

Link: Lituo

 


        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;

 The logic is the same as traversing the entire binary tree to find a value.

Flip a binary tree:

Link: Lituo

Idea: In the face of recursive problems, we should not directly focus on solving a whole tree, but what to do at each step. The logic of each step of the main body of this problem is to replace the left and right subtrees, so we don’t need to think too much. Directly swap the left and right subtrees, and leave the rest to recursive processing, without taking too much care of the overall situation.

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;

    }
};

 same tree:

Link: Lituo

Idea: The same as the flip above, we only need to pay attention to whether the value of each node comparison meets the requirements, and the rest is left to recursion

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 ;


}

 

Layer order traversal:

Since the consumption of recursive stack frames is still relatively large, it is still necessary to use a non-recursive method to traverse the binary tree. With the help of the first-in-first-out feature of the queue, non-recursive traversal can be achieved very well.

Idea: Binary tree is nothing more than the problem of root and left subtree and right subtree. Logically speaking, when we reach a node, the next step is to get its value or left subtree and right subtree, then we only need to first Put the root node into the queue, then put the left subtree and the right subtree of the root into the queue, and after the root is out of the queue, treat its left and right subtrees as new roots, and then split them into left and right subtrees to achieve the level-order traversal Effect.

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

 

Guess you like

Origin blog.csdn.net/m0_53607711/article/details/128331361