[Data structure] Chained implementation and traversal of binary trees


Insert image description here

1. Binary tree traversal

The binary tree nodes in all the codes below:

typedef char BTDataType;
//二叉树结点结构体
typedef struct BinaryTreeNode
{
    
    
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

1. Preorder traversal

Preorder, middle, and postorder traversals can all be solved using the idea of ​​divide-and-conquer recursion, and the root node and its child nodes are processed separately.

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    printf("%c ", root->data);
    BinaryTreePrevOrder(root->left);
    BinaryTreePrevOrder(root->right);
}

Here we only use the recursive expansion graph to analyze pre-order traversal. The same idea is used in in-order and post-order:

Insert image description here

Insert image description here

2. In-order traversal

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreeInOrder(root->left);
    printf("%c ", root->data);
    BinaryTreeInOrder(root->right);
}

3. Post-order traversal

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreePostOrder(root->left);
    BinaryTreePostOrder(root->right);
    printf("%c ", root->data);
}

4. Layer sequential traversal

Level order traversal needs to be performed using a queue. If the binary tree and node are not empty, letenqueue a pointer to it, then record the head node of the queue, print its value first, then judge that its left and right children are non-empty and then join the queue, then delete the head of the queue and replace it with the next one to continue recording and printing... until the queue is empty and the traversal is completed.

For example, consider this binary tree as shown:

The result of layer sequence traversal is: 12345.
Insert image description here
First, put the root node 1 into the queue and print 1

Insert image description here

Then add the left and right children 2 and 3 of 1 into the team
Insert image description here

Delete the head of the queue 1, replace front with 2, and print 2
Insert image description here

Then add the left child 4 of 2 to the team
Insert image description here

Delete the head 2, replace front with 3, and print 3
Insert image description here

Then add the right child 5 of 3 to the team
Insert image description here

… …

Then print 4 and 5 like this to complete the level-order traversal of the binary tree.

Insert image description here

The program code uses the queue created by itself. The code is as follows:

//层序遍历
void LevelOrder(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        //将队头打印
        BTNode* front = QueueFront(&q);
        printf("%c ", front->data);
        //判断front左右节点不为空则入队
        if (front->left)
            QueuePush(&q, front->left);

        if (front->right)
            QueuePush(&q, front->right);
        
        QueuePop(&q);
    }
    printf("\n");

    QueueDestroy(&q);
}

2. Number and height of binary tree nodes

1. Number of binary tree nodes

It is implemented recursively using the divide-and-conquer method. When the root node is empty, the return value is 0. If it is not empty, it returns the number of nodes on the left and right subtrees plus 1.

int BinaryTreeSize(BTNode* root)
{
    
    
    return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

2. Number of leaf nodes of binary tree

It is implemented recursively using the divide-and-conquer method. When the root node is empty, 0 is returned. When the root node has no child nodes, it means it is a leaf node, and 1 is returned. In other cases, just add the leaf nodes on the left and right subtrees.

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

3. Number of nodes at the kth level of the binary tree

You need to ensure that k is greater than 0. When the root node is empty, 0 is returned. When k is equal to 1, there is only one node in one layer, and 1 is returned. When k>1, the number of nodes in the kth layer is equivalent to the kth child of its left and right children. -The number of nodes in layer 1 is added up.

int BinaryTreeLevelKSize(BTNode* 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);
}

4. Find the node with value x in a binary tree

If the following node is empty, NULL is returned if it cannot be found. When the value of the root node is the value you are looking for, the node is returned. If they are not equal, its left and right child nodes are judged respectively until they are found.

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
    
    
    if (root == NULL)
    {
    
    
        return NULL;
    }
    if (root->data == x)
    {
    
    
        return root;
    }
    BTNode* ret = BinaryTreeFind(root->left,x);
    if (ret)
    {
    
    
        return ret;
    }
    return BinaryTreeFind(root->right, x);
}

3. Binary tree creation and destruction

1. Create a binary tree by traversing the array in preorder

Read a preorder traversal string input by the user, and build a binary tree (stored as a pointer) based on this string. For example, the following pre-order traversal string: ABC##DE#G##F### where "#" represents a space, and the space character represents an empty tree. After establishing the binary tree, perform an in-order traversal on the binary tree and output the traversal results.

#include <stdio.h>
#include<stdlib.h>
typedef char BTDataType;

typedef struct BinaryTreeNode {
    
    
    BTDataType data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
} BTNode;
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
    
    
    if (a[*pi] == '#') {
    
    
        ++*pi;
        return NULL;
    }

    BTNode* root = (BTNode*)malloc(sizeof(BTDataType));
    root->data = a[*pi];
    ++*pi;

    root->left = BinaryTreeCreate(a, pi);
    root->right = BinaryTreeCreate(a, pi);

    return root;
}
//中序遍历
void InOrder(BTNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return;
    }
    InOrder(root->left);
    printf("%c ",root->data);
    InOrder(root->right);
}
int main() {
    
    
    char a[100];
    scanf("%s",a);
    int pi=0;
    BTNode* root=BinaryTreeCreate(a, &pi);
    InOrder(root);
    return 0;
}

2. Destruction of binary trees

void BinaryTreeDestory(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }

    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    free(root);
}

3. Determine whether it is a complete binary tree

Modify the binary tree level-order traversal so that empty nodes also enter the queue. When traversing an empty node, it will exit. If there are non-empty nodes before the end of the traversal, it is not a complete binary tree.

int BinaryTreeComplete(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front == NULL)
        {
    
    
            break;
        }
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
        QueuePop(&q);
    }
    //此时已经遇到空节点,如果再遇到非空节点则不是完全二叉树
    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front)
        {
    
    
            QueueDestroy(&q);
            return false;
        }
        QueuePop(&q);
    }

    QueueDestroy(&q);
    return true;
}

4. Test code

Manually build a binary tree as shown below and test the code:
Insert image description here
the test result should be:

Preorder: 123874569
Middle sequence: 832715469
Postorder: 837259641

Whether it is a complete binary tree: 0
Number of nodes: 9
Number of leaf nodes: 4

BTNode* BuyNode(BTDataType x)
{
    
    
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if (node == NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }

    node->data = x;
    node->left = NULL;
    node->right = NULL;

    return node;
}


int main()
{
    
    
    	// 手动构建
	BTNode* node1 = BuyNode('1');
	BTNode* node2 = BuyNode('2');
	BTNode* node3 = BuyNode('3');
	BTNode* node4 = BuyNode('4');
	BTNode* node5 = BuyNode('5');
	BTNode* node6 = BuyNode('6');
	BTNode* node7 = BuyNode('7');
	BTNode* node8 = BuyNode('8');
	BTNode* node9 = BuyNode('9');

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	node2->right = node7;
	node3->left = node8;
	node6->right = node9;

    printf("前序遍历:");
    BinaryTreePrevOrder(node1);
	printf("\n");

    printf("中序遍历:");
    BinaryTreeInOrder(node1);
	printf("\n");

    printf("后序遍历:");
    BinaryTreePostOrder(node1);
	printf("\n");

    printf("层序遍历:");
    LevelOrder(node1);
    printf("\n");

    printf("BinaryTreeComplete:%d\n", BinaryTreeComplete(node1));
    printf("BinaryTreeSize:%d\n", BinaryTreeSize(node1));
    printf("BinaryTreeLeafSize:%d\n", BinaryTreeLeafSize(node1));

    BinaryTreeDestory(node1);
	node1 = NULL;

    return 0;
}

operation result:

Insert image description here
The running results are consistent with the predicted results.

Guess you like

Origin blog.csdn.net/zcxyywd/article/details/133107365