【Data Structure Learning Record 14】——Tree and Binary Tree

Zero. Foreword

There should have been the last chapter 稀疏矩阵的十字链表存储and 广义表.
But the generalized table is more biased towards the topic, understand the concept, and be able to calculate it. To some extent, the generalized table can be regarded as a tree.

1. Tree

1. Definition

The tree is a finite set of n (>=0) nodes.

2. Nature

In any non-empty tree:

  1. There is one and only one specific node called根结点root
  2. When n>1, the remaining nodes can be divided into m>0disjoint finite sets T . 1 ...... T m . Among them, each set itself is a tree, and is called the root 子树.

Therefore, the definition of the tree structure should be a recursive definition.

3. Representation

In addition to our common tree diagram representation, there are:

  1. Nested set notation (a)
  2. Generalized table notation (b)
  3. Recessed notation ©
    Insert picture description here

4. Basic terminology

  1. The tree 结点contains a data element and several branches that point to its subtrees.
  2. 结点The owned subtree is called 结点的度(Degree).
  3. A node with a degree of 0 is called an 叶子OR 终端结点.
  4. The node whose degree is not 0 is called 分支结点or非终端结点
  5. 树的度Is the maximum degree of each node in the tree.
  6. The root of a node's subtree is called the node's 孩子; correspondingly, the node is a child 双亲.
  7. Nodes of the same parent, they are called each other兄弟
  8. The level of the node is defined from the root, the root is the first level, and the children of the root are in the second level. If a node is on level n, then the root of its subtree is on level n+1. Nodes with parents on the same level are called 堂兄弟.
  9. The largest level of nodes in the tree is called the tree's 深度或高度.
  10. If the subtrees are regarded as ordered from left to right, then the tree is said to be 有序树, otherwise it is 无序树.
  11. In an ordered tree, the root of the leftmost subtree is called 第一个孩子, and the rightmost is called最后一个孩子
  12. 森林It is m>=0a collection of disjoint trees. For each node in the tree, the collection of its subtrees becomes the forest.

In terms of logical structure, any tree is a two-tuple Tree=(root,F), where root is a data element, called the root node of the tree; F is a forest of m>=0 trees, F= (T . 1 ...... T m ), where T i = (R & lt i , F. i called i-th root of root subtree.
Insert picture description here

Two. Binary Tree

1. Small introduction

If you study a tree, you must start with the simplest case. When each of our nodes has a child, isn't this a linked list? So when we study trees, we generally use a tree with two children at the node, called a binary tree.

2. Nature

Here are some properties without proof. It is also easy to prove (probably).

  1. There iare at most 2 i-1 nodes on the first level of the binary tree .
  2. A binary tree of depth k has at most 2 k -1 nodes (k>=1).
  3. For any binary tree. If the number of terminal nodes is m and the number of nodes with degree 2 is n, then m=n+1.
  4. A binary tree with a depth of k and 2 k -1 nodes is called 满二叉树.
  5. The full binary tree is numbered, and it is agreed that the numbering starts from the root node, from top to bottom, and from left to right. When each node of a tree corresponds to the full binary tree in this way, it is called 完全二叉树. It has two characteristics: a) Leaf nodes can only appear on the two largest levels. b) For any node, the maximum level of descendants under the right branch is l, then the maximum level of descendants under the lower left branch must be l or l+1.
  6. The depth of a complete binary tree with n nodes is log 2 n +1
  7. If there is a complete binary tree with n nodes, and following the numbering method just described, for any node i (1<=i<=n), there are: a) If i=1, then node i is a binary tree The roots, without parents. If i>1, the number of the parent node is i/2. b) If 2i>n, the node has no left child, otherwise its left child is node 2i. c) If 2i+1>n, then node i has no right child, otherwise the number of its right child is node 2i+1.
    Insert picture description here

3. The storage structure of the binary tree

3.1 Sequence storage

Insert picture description here

Sequential storage is generally used for complete binary trees. If used in an incomplete binary tree, it may cause a lot of waste of space.

3.2 Binary Linked List

Insert picture description here

From the structure point of view, a node has left and right pointer fields in addition to the data field. Then the simplest linked list contains these three parts. It can be understood as a singly linked list X2.

3.3 Three-pronged linked list

In a three-pronged linked list, it has one more parent node pointer than a two-pronged linked list. It is very similar to a doubly linked list.

4. Traversal of Binary Tree

4.1 Definition

In some applications of binary trees, it is often required to find points with certain characteristics in the tree, or to perform certain processing on all the nodes in the tree one by one. This raises a 遍历二叉树question. Patrol each node in the tree according to a certain search path, so that each node is only visited once. Suppose we have a complete binary tree of 1234567 as an example of the next three traversals. Traversal is based on operations on non-empty nodes.

4.2 Pre-order traversal

  1. Visit the root node.
  2. Traverse the left subtree first.
  3. Traverse the right subtree first.
  4. Traverse results: 1245367

4.3 In-order traversal

  1. Traverse the left subtree in middle order.
  2. Visit the root node.
  3. Traverse the right subtree in middle order.
  4. Traverse results: 4251637

4.4 Post-order traversal

  1. Traverse the left subtree in post-order.
  2. Traverse the right subtree in post-order.
  3. Visit the root node.
  4. Traverse the result 4526731

Three. Principles of Programming

1. Storage structure

In this article, we use the simplest binary linked list + traversal implementation. First, we still create a data domain structure, and then a node structure, which contains two pointers to the left and right son nodes and a data domain structure.

2. Storage (first-order traversal)

We read in a tree and construct this binary tree through the method of pre-order traversal. Of course, in order to know the terminal node of each tree, we need to represent the son of the terminal node with a virtual node, a random character. The agreement here is #, for example, for ABCthis tree with a depth of 2, we need to input AB##C##.
Our traversal should be traversed to the virtual node, if the character is #then, the node value is NULL, if not #, the data field of the node is stored in the character, and the son node is created.

3. Traverse the output

If we have a #node, then stop recursion, it is recursion our borders.
Otherwise, just follow a certain traversal method to traverse and output the node characters.

Four. Code implementation

#include <stdio.h>
#include <stdlib.h>

#define         OK      1
#define         ERROR   0

typedef struct dataType{
    
    
    char data;
}dataType;

typedef struct Btree{
    
    
    dataType node;
    struct Btree *lc;
    struct Btree *rc;
}Btree;

int BtreeCreat(Btree **TreePtr);    // 通过先序遍历的方式创建二叉树
int BtreeShowDLR(Btree *root);      // 三种遍历
int BtreeShowLDR(Btree *root);
int BtreeShowLRD(Btree *root);

int main()
{
    
    
    Btree *root = NULL;
    printf("\nplase input the tree as DLR:\n");
    BtreeCreat(&root);
    printf("\nDLR is: ");
    BtreeShowDLR(root);
    printf("\nLDR is: ");
    BtreeShowLDR(root);
    printf("\nLRD is: ");
    BtreeShowLRD(root);
    return 0;
}

int BtreeCreat(Btree **TreePtr)
{
    
    
    // 因为会对传入的结点的地址进行修改,所以需要用到二重指针
    char ch;
    ch = getchar();  //读入字符
    if (ch == '#')
    {
    
    
        *TreePtr = NULL;    // 如果这个字符是#,则将这个结点的地址赋为空
    }
    else    //非空
    {
    
    
        *TreePtr = (Btree*)malloc(sizeof(Btree));   // 创建结点
        if (!*TreePtr) return ERROR;        // 创建失败退出
        (*TreePtr)->node.data = ch;         // 将结点的值赋值为字符
        BtreeCreat(&((*TreePtr)->lc));      // 遍历创建左结点
        BtreeCreat(&((*TreePtr)->rc));      // 遍历创建右结点
    }

    return OK;
}

int BtreeShowDLR(Btree *root)   // 因为遍历不会对结点地址进行改变,所以不需要二重指针
{
    
    
    if (root != NULL)   // 如果结点不为空,说明它有值
    {
    
    
        printf("%c", root->node.data);  // 输出根结点
        BtreeShowDLR(root->lc);         // 遍历左结点
        BtreeShowDLR(root->rc);         // 遍历右结点
    }
    // 为空没有任何操作
    return OK;
}

int BtreeShowLDR(Btree *root)
{
    
    
    if (root != NULL)   // 遍历顺序不一样
    {
    
    
        BtreeShowLDR(root->lc);
        printf("%c", root->node.data);
        BtreeShowLDR(root->rc);
    }
    return OK;
}

int BtreeShowLRD(Btree *root)
{
    
    
    if (root != NULL)   // 遍历顺序不一样
    {
    
    
        BtreeShowLRD(root->lc);
        BtreeShowLRD(root->rc);
        printf("%c", root->node.data);
    }
    return OK;
}

Guess you like

Origin blog.csdn.net/u011017694/article/details/109859754