# definition

A finite set T composed of multiple nodes with and only one node is called root

# Structural features

- Nonlinear structures have a direct precursor, but can have multiple successors
- It is recursive, and there are trees in the tree
- The tree can be empty

# Related terms

- Root node
- Leaf terminal node
- The forest is a collection of m disjoint trees
- Each subtree of the ordered tree node is ordered from left to right and cannot be interchanged
- A tree in which the subtrees of an unordered tree can be interchanged
- Parental direct precursor
- Child direct successor
- The same level node of brothers and parents
- A node where cousins and parents are on the same level (but not the same parents)
- Ancestor all nodes from the root to the branch of the node
- All nodes of the node subtree
- Data elements of node tree
- The degree of the node and the number of subtrees attached to the node (several direct successors are several degrees)
- The number of layers from the root to the node (the root node is the first layer)
- Node with terminal node degree of 0 (leaf)
- Branch node nodes other than the root (internal nodes)
- The degree of a tree is the maximum of all node degrees
- The depth or height of the tree and the maximum number of layers of all nodes

# Tree storage

## Parental representation

struct Node { int data; int parent; }

## Child representation

struct Node { int data; ChildList* chead; //The head node of the linked list composed of children }

## Left child right brother notation

struct Node { int data; int child; int brother; }

# Binary tree

## characteristic

- Ordered tree
- The degree of each node is less than or equal to 2

## nature

- There are at most 2^(i - 1) nodes on the i-th layer of a binary tree
- A binary tree with depth K has at most 2^k - 1 nodes
- For any binary tree, if the number of nodes with degree 2 is n2, the number of leaves is n2 + 1
- The depth of a complete binary tree with n nodes must be floor(log2(n)) + 1
- The complete binary tree is numbered from top to bottom and from left to right. For the node numbered i, the left child is 2i and the right child is 2i + 1

## Special binary tree

### Full binary tree

For a binary tree with depth K, 2^k + 1 nodes is called a full binary tree

### Complete binary tree

The first k - 1 layer is full, and only the last layer lacks the binary tree on the right

### Balanced binary tree BBT

It is an empty tree or the absolute value of the height difference between its left and right subtrees does not exceed 1, and both the left and right subtrees are a balanced binary tree.

This scheme solves the problem that the binary search tree degenerates into a linked list, and maintains the time complexity of insertion, search and deletion at O(logN) in the best and worst cases. However, frequent rotation will sacrifice about O(logN) time for insertion and deletion, but it is much more stable in time than binary search tree.

### Binary search tree BST

Search binary tree is a special ordered binary tree. If a tree is not empty, and if the left subtree of its root node is not empty, the values of all nodes above its left subtree are less than the values of its root node. If its right subtree is not empty, the values of any node of its right subtree are greater than the values of its root node, and its left and right subtrees are also binary search trees.

It can be seen that if the binary search tree is arranged in middle order (left, middle and right), a sequence from small to large will be obtained

## Storage of binary tree

struct BitNode { int data; struct BitNode *lchild, *rchild; }

struct BitNode { int data; struct BitNode *lchild, *rchild; struct BitNode *parent; }

## Traversal of binary tree

No matter what method is used, the view of each node is from left to right, and from middle to bottom refers to the location of the root node. In general, there are recursive traversal and non recursive traversal.

### Preorder traversal DLR

(data lchild rchild)

void DLRprint(BinaryNode* root) { if (root == NULL) { return; } //Access the root node first printf("%c", root->ch); //Then traverse the left subtree DLRprint(root->lchild); //Then traverse the right subtree DLRprint(root->rchild); } void DLRprint2(BinaryNode* root) { if (root == NULL) { return; } BinaryNode* stack[MAX_SIZE] = { NULL }; //Stack storage int flag[MAX_SIZE] = { 0 }; //The flag bit corresponding to each element in the stack can be printed if it is true int top = 0; //Stack top pointer stack[top] = root; top++; while (top != 0) { BinaryNode* tmp = stack[top - 1]; if (flag[top - 1] == 1) { top--; printf("%c", tmp->ch); } else { top--; if (tmp->rchild != NULL) //First in and last out, so reverse storage { stack[top] = tmp->rchild; flag[top] = 0; top++; } if (tmp->lchild != NULL) { stack[top] = tmp->lchild; flag[top] = 0; top++; } stack[top] = tmp; flag[top] = 1; top++; } } }

### Middle order traversal LDR

void LDRprint(BinaryNode* root) { if (root == NULL) { return; } //Traverse left subtree LDRprint(root->lchild); //Access root node printf("%c", root->ch); //Traversing right subtree LDRprint(root->rchild); } void LDRprint2(BinaryNode* root) { if (root == NULL) { return; } BinaryNode* stack[MAX_SIZE] = { NULL }; //Stack storage int flag[MAX_SIZE] = { 0 }; //The flag bit corresponding to each element in the stack can be printed if it is true int top = 0; //Stack top pointer stack[top] = root; top++; while (top != 0) { BinaryNode* tmp = stack[top - 1]; if (flag[top - 1] == 1) { top--; printf("%c", tmp->ch); } else { top--; if (tmp->rchild != NULL) //First in and last out, so reverse storage { stack[top] = tmp->rchild; flag[top] = 0; top++; } stack[top] = tmp; flag[top] = 1; top++; if (tmp->lchild != NULL) { stack[top] = tmp->lchild; flag[top] = 0; top++; } } } }

### Post order traversal LRD

void LRDprint(BinaryNode* root) { if (root == NULL) { return; } //Traverse left subtree LRDprint(root->lchild); //Traversing right subtree LRDprint(root->rchild); //Access root node printf("%c", root->ch); } void LRDprint2(BinaryNode* root) { if (root == NULL) { return; } BinaryNode* stack[MAX_SIZE] = { NULL }; //Stack storage int flag[MAX_SIZE] = { 0 }; //The flag bit corresponding to each element in the stack can be printed if it is true int top = 0; //Stack top pointer stack[top] = root; top++; while (top != 0) { BinaryNode* tmp = stack[top - 1]; if (flag[top - 1] == 1) { top--; printf("%c", tmp->ch); } else { top--; stack[top] = tmp; //First in and last out, so reverse storage flag[top] = 1; top++; if (tmp->rchild != NULL) { stack[top] = tmp->rchild; flag[top] = 0; top++; } if (tmp->lchild != NULL) { stack[top] = tmp->lchild; flag[top] = 0; top++; } } } }

## How to determine the shape of binary tree

### Middle first traversal and middle second traversal determination

- A tree can be determined by middle order traversal and pre order traversal
- Through middle order traversal and post order traversal, a tree can be determined
- Only the root element can be solved in separate order first and then

Principle: determine the root element by first order traversal, then judge the left and right subtree elements according to the middle order traversal results, and then recursively determine the left and right subtrees in the same way

### Well number creation method

Fill each node of the tree with a # number into a tree with a degree of 2

Equivalent to # a leaf node, which identifies the boundaries of the left and right subtrees

//Well number creation tree method BinaryNode* CreateBinaryTree() { char ch; scanf("%c", &ch); int c; while ((c = getchar()) != '\n' && c != EOF); //There are carriage returns left. Clear the buffer if (ch == '#') { return NULL; } else { BinaryNode* newnode = (BinaryNode*)malloc(sizeof(BinaryNode)); newnode->lchild = CreateBinaryTree(); newnode->rchild = CreateBinaryTree(); newnode->ch = ch; return newnode; } }

## Related terms

- Precursor node Previous node in middle order traversal
- Successor node The next node in the middle order traversal

## Recursive routine

- Assuming that the X node is the head, it is assumed that any information can be asked from the X left tree and the X right tree
- Under the assumption of the previous step, discuss the possibility of obtaining the answer for the tree with X as the head node (the common classification is related or independent of x)
- After listing all the possibilities, determine what information you need from the left tree and the right tree
- Finding the complete set of left tree information and right tree information is the information S that any subtree needs to return
- Recursive functions return S, which is required for each subtree
- Write code and consider how to integrate the information of the left tree and the information of the right tree into the information of the whole tree

## example

### Equilibrium solution

Get information: whether the left tree is balanced and the right tree is balanced. Whether the left tree height is balanced and the right tree height is balanced

The possibility of getting an answer is the only one

void fun1(BinaryNode* root, int* isBalance, int* height) { if (root == NULL) { return; } int l_isBalance = 1, r_isBalance = 1; int l_height = 0, r_height = 0; fun1(root->lchild, &l_isBalance, &l_height); fun1(root->rchild, &r_isBalance, &r_height); *height = (l_height > r_height ? l_height : r_height) + 1; *isBalance = 1; if (l_isBalance == 0 || r_isBalance == 0 || abs(l_height - r_height) > 1) { *isBalance = 0; } return; }

### Maximum distance between any two nodes

Get information: maximum distance from left tree to left tree height maximum distance from right tree to right tree height

Possibility judgment:

- The maximum distance through the root node is equal to the height of the left tree + 1 + the height of the right tree
- The maximum distance does not pass through the root node and is equal to the maximum value of the maximum distance of the left tree and the maximum distance of the right tree

Finally, compare the two possibilities, which is the maximum distance

typedef struct INFO2 { int maxDistance; int height; } Info2; Info2 fun2(BinaryNode* root) { if (root == NULL) { Info2 info = { 0, 0 }; return info; } Info2 l_info = fun2(root->lchild); Info2 r_info = fun2(root->rchild); int max1 = l_info.maxDistance > r_info.maxDistance ? l_info.maxDistance : r_info.maxDistance; int max2 = l_info.height + 1 + r_info.height; Info2 res = { max1 > max2 ? max1 : max2, (l_info.height > r_info.height ? l_info.height : r_info.height) + 1 }; return res; }

### Maximum binary search subtree size

Get information: the maximum BST size of the left tree, whether the left tree is BST, the maximum value of the left tree, the maximum BST size of the right tree, whether the right tree is BST, and the minimum value of the right tree

The information obtained by the two trees is different, but recursion is required, so the information is combined as the return value

Possibility judgment:

- The maximum BST does not pass through the root node. Equal to the one with the largest BST on the left and right
- The maximum BST passes through the root. It is equivalent to a BST as a whole. It is obtained when the left is empty or BST, and the right is also empty or BST, and the root value is greater than the maximum value on the left and less than the minimum value on the right.

typedef struct INFO3 { int maxBSTSize; int isBST; int max; int min; } Info3; //Find maximum binary search subtree size Info3 fun3(BinaryNode* root) { if (root == NULL) { Info3 err = { -1, -1, -1, -1 }; //Use - 1 to indicate that the information is NULL return err; } Info3 l_info = fun3(root->lchild); Info3 r_info = fun3(root->rchild); int max = root->data; int min = root->data; int maxBSTSize = 0; int isBST = 0; if (l_info.maxBSTSize != -1) { max = l_info.max > max ? l_info.max : max; min = l_info.min < min ? l_info.min : min; } if (r_info.maxBSTSize != -1) { max = r_info.max > max ? r_info.max : max; min = r_info.min < min ? r_info.min : min; } if (l_info.maxBSTSize != -1) { maxBSTSize = l_info.maxBSTSize; } if (r_info.maxBSTSize != -1) { maxBSTSize = r_info.maxBSTSize > maxBSTSize ? r_info.maxBSTSize : maxBSTSize; } if ((l_info.isBST == 1 || l_info.maxBSTSize == -1) && (r_info.isBST == 1 || r_info.maxBSTSize == -1)) { if ((l_info.maxBSTSize == -1 || root->data > l_info.max) && (r_info.maxBSTSize == -1 || root->data < r_info.min)) { isBST = 1; maxBSTSize = (l_info.maxBSTSize == -1 ? 0 : l_info.maxBSTSize) + (r_info.maxBSTSize == -1 ? 0 : r_info.maxBSTSize) + 1; } } Info3 info = { maxBSTSize, isBST, max, min }; return info; }