This is the story about "Mr. Tree"


insert image description here


"Data Structure Column"



1. Understand the tree structure

Definition of tree: Tree refers to a collection of hierarchical relationships composed of N (N>=0) finite nodes, which is a simple nonlinear structure. When N=0, it is called an empty tree.

How to traverse the tree

前序遍历
insert image description here

中序遍历
insert image description here

后序遍历
insert image description here

For the front-middle-post-order traversal, the position of the root node is used to determine the pre-inorder.

层序遍历

For the layer sequence, it is traversing layer by layer, and the node data of the next layer is brought in after the root node of the upper layer is traversed. A container of auxiliary queues can be used to implement sequential traversal.
insert image description here
代码实现

//层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	Queue qu;
	BTNode* cur;

	QueueInit(&qu);

	QueuePush(&qu, root);

	while (! QueueEmpty(&qu))
	{
    
    
		cur = QueueFront(&qu);

		putchar(cur->_data);

		if (cur->_left)
		{
    
    
			QueuePush(&qu, cur->_left);
		}

		if (cur->_right)
		{
    
    
			QueuePush(&qu, cur->_right);
		}

		QueuePop(&qu);
	}

	QueueDestory(&qu);
}

How to create a tree?

The traversal of a binary tree is pre-order, middle-order and post-order traversal. For pre-order and post-order traversal, the root node can be found quickly. Then distinguish the left and right subtrees through inorder. Realize the construction of the tree.

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
Input: abc ## de #g ## f ###
Output: cbegdfa

When building a tree,
insert image description here
the input is an array for data storage, so a data record array subscript needs to be used when building a tree node.
insert image description here
Avoid returning to reset the subscript after using the subscript of the array during recursion. Here, it is necessary to keep the subscript of the array consistent and go backwards. Only after the recursion comes out will the entire array be traversed. A preamble thought-building tree used.

typedef  struct TreeNode
{
    
    
    struct TreeNode* left;
    struct TreeNode* right;
    char val;
}TreeNode;

TreeNode* makeTree(char* arr,int *count)
{
    
    
    if(arr[*count]=='#'||arr[*count]==' ')
    {
    
    
        return NULL;
    }

    TreeNode* newnode=(TreeNode*)malloc(sizeof(TreeNode));
    newnode->val=arr[(*count)++];

    newnode->left=makeTree(arr, count);
    (*count)++;
    newnode->right=makeTree(arr, count);

    return newnode;
}

void InOrder(TreeNode*root)
{
    
    
    if(root==NULL)
    return ;

    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}

int main()
{
    
    

    char arr[101];
    scanf("%s",arr);
    int count=0;
    TreeNode*tree=makeTree(arr, &count);
    InOrder(tree);
    return 0;
}

How to judge whether a tree is a complete binary tree?

insert image description here
By comparing the full binary tree and the complete binary tree, it is found that the number of bottom leaf nodes of the complete binary tree decreases from left to right, so the number of layers with a height of n-1 is the same as the full binary tree. For the last one of the complete binary tree layer for analysis.

For a complete binary tree with n nodes, if all nodes are numbered from 0 according to the order of the array from top to bottom and from left to right, then for the
node with the sequence number i:

  1. If i>0, the parent number of the node at i position: (i-1)/2; i=0, i is the root node number, no parent node
  2. If 2i+1<n, left child number: 2i+1, 2i+1>=n otherwise there is no left child
  3. If 2i+2<n, the right child number: 2i+2, 2i+2>=n otherwise there is no right child

代码实现

int BinaryTreeComplete(BTNode* root)
{
    
    
	Queue qu;
	BTNode* cur;
	int tag = 0;

	QueueInit(&qu);

	QueuePush(&qu, root);

	while (! QueueEmpty(&qu))
	{
    
    
		cur = QueueFront(&qu);

		putchar(cur->_data);

		if (cur->_right && !cur->_left)
		{
    
    
			return 0;
		}

		if (tag && (cur->_right || cur->_left))
		{
    
    
			return 0;
		}

		if (cur->_left)
		{
    
    
			QueuePush(&qu, cur->_left);
		}

		if (cur->_right)
		{
    
    
			QueuePush(&qu, cur->_right);
		}
		else
		{
    
    
			tag = 1;
		}

		QueuePop(&qu);
	}

	BinaryTreeDestory(&qu);
	return 1;
}

Two, the simple algorithm of the tree - recursion

1. Same tree

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的
insert image description here

The same understanding of the topic should be that the node data is the same data, and the left and right subtree structures are also the same. The judgment of the empty tree should also be discussed. One of the trees is empty, and the other tree is not empty, which is obviously not the case. the same number. The judgment condition is the val value, whether the left and right subtree structures are empty at the same time (judging whether they are all leaf nodes).

class Solution {
    
    
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
    
    
        if(p==nullptr&&q==nullptr)return true;
        
        if(p==nullptr||q==nullptr)return false;

       if(q->val!=p->val)return false;


        return isSameTree(q->left,p->left)&&isSameTree(q->right,p->right);
    }
};

2. Mirror tree

给你一个二叉树的根节点 root , 检查它是否轴对称
insert image description here

The mirror image tree and the solution are somewhat similar to the same tree above, but there is a slight difference in that the tree structure comparison is that the left subtree and the right subtree are symmetrical, and the logic of the same tree is used to solve the problem.

class Solution {
    
    
public:
    bool issametree(TreeNode* root,TreeNode* subroot)
    {
    
    
        if(root==nullptr && subroot==nullptr)
        {
    
    
            return true;
        }
        if(root==nullptr || subroot==nullptr)
        {
    
    
            return false;
        }
         
        if(root->val==subroot->val)
        {
    
    
            return issametree(root->left,subroot->right) && issametree(root->right,subroot->left);
        }
        else
        {
    
    
            return false;
        }
    }
    bool isSymmetric(TreeNode* root) {
    
    
        if(root==nullptr) return true;
        return issametree(root->left,root->right);
    }
};

3. Single-valued binary tree

topic:如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时,才返回 true;否则返回 false。
insert image description here

It is a relatively common algorithm to find the value in the binary tree, using depth traversal, traversing from the left subtree to the right subtree in turn. It is not possible to compare the left and right subtrees after adding node data. There will be multiple nodes on the left and only one node data on the right. But the values ​​of the left and right subtrees are still equal. So you need to get va from the root to compare and judge the left and right subtrees.

class Solution {
    
    
public:
    bool isUnivalTree(TreeNode* root) {
    
    
        if(root==nullptr)return true;

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

Summarize

The structure of the tree is easy to understand using a recursive algorithm to traverse, but for a tree that is too deep, a stack overflow will occur. Trees are obviously not a good choice for storing data, as crooked-neck trees and single trees are prone to appear. low efficiency. It can be optimized later to become a search binary tree, AVL tree...

Guess you like

Origin blog.csdn.net/github_73587650/article/details/130774817