Binary Tree Padding  Tree
In the previous articles, the linear table, stack, queue, string, and so on, which we have mainly introduced, are onetoone linear structures. Today we are explaining "tree" is a typical nonlinear structure. The feature of the nonlinear structure is that the direct precursor of any node, if it exists, must be unique, if it exists, then there can be more than one.It can also be interpreted as a onetomany relationship, so let's first get to know trees
The concept of trees
The following picture shows the trees we see in our daily life. From the main tree trunk, we can see that many branches are derived upwards, and from each branch, we can see some branches. This makes up the structure of the trees we can see on the ground, but for each branch, it is derived from the main tree trunk layer by layer.
We often need to solve such practical problems in our computers as:
 Used to store and process treelike data, such as genealogy, organization charts
 Lookup and some largescale data indexing aspects
 Efficient sorting of data
Without mentioning some complex functions, such as modeling some data with tree hierarchy to solve practical problems, we can use the structure of "tree" to represent it. In order to better suit our habits, we usually look at "tree" upside down, and we can summarize it as the following structure, which is also in our data structure"Tree"
Common terms in trees

Node: A branch that contains both data items and points to other nodes, such as Circle A in the figure above, which contains both data items A and B and C.

In particular, because A has no precursor and only one, it is called the root node.

Subtree: A subtree of a tree is a subtree derived from the root node and all descendants of the root node.
 For example, the two figures below are subtrees of the tree above

Node Degree: The number of subtrees a node has, simply by looking directly at how many branches it has, such as degree A above is 2 and degree B above is 1

Leaf node: Also known as terminal node, i.e. node without a successor, e.g. E F G H I

Branch node: Also known as nonterminal node, this can be called except leaf node

Child Node: Also known as Son Node, which is the immediate successor of a node, such as B and C are children nodes of A

Parent Node: Also known as parent node, a direct precursor of a node, e.g. A is the parent node of B and C

Brothers node: Children nodes of the same parent are called brothers to each other, e.g. B and C are brothers to each other

Cousins: Nodes where parents are brothers, e.g. D and E are cousins to each other

Ancestor node: All nodes on the path from the root node to a node, A B D node is the ancestor node of H node

Descendant node: Any node in a subtree whose root is a node is called a descendant node of that node, for example, the descendant node of C has an E F I

Hierarchy of nodes: Set the root node hierarchy to 1, and the remaining nodes to add 1 to their parent node hierarchy, for example, Level A to 1, Level B to 2

The height of a tree: Also known as the depth of a tree, the maximum level of nodes in a tree

Ordered/Unordered Tree: Whether node subtrees in a tree are ordered from left to right, ordered is ordered tree, and disordered is disordered tree
As you may also see, in the example I mentioned above, the branches are all within two, which is a kind of tree we focus on today  "binary tree"
Binary Tree
In computer science, a Binary tree is a tree structure where each node has at most two branches (that is, there is no node with a branch greater than 2).Branches are often referred to as "left subtrees" or "right subtrees".The branches of a Binary tree have leftright order and cannot be reversed at will. Wikipedia
Specifically emphasized by definition:
 Each node has at most two branches, not two branches, but the maximum, none or only one is possible
 The left subtree and the right subtree must have a clear order, even if there is only one subtree, whether it is a left subtree or a right subtree
Several Special Binary Trees
(1) Full Binary Tree
Typically, the trees we see are both high and low, with uneven hierarchies. If a binary tree has a maximum number of nodes at any level, such a tree is called a full binary tree, and a binary tree with a height of K has 2<sup>k</sup>  1 node at a time
(2) Complete Binary Tree
Complete binary trees are highly efficient data structures. Complete binary trees are derived from full binary trees.A binary tree with n nodes at depth K is called a complete binary tree if and only if each node corresponds to onetoone numbers from 1 to N in a full binary tree at depth K
How to quickly determine if a complete binary tree is true:
 A binary tree can be a complete binary tree if only the lowest two levels of nodes are less than 2 and the lowest level of nodes are concentrated in the leftmost contiguous position of that level.
 Looking at the diagram of the tree, I silently numbered the tree hierarchically according to the structure of the full binary tree. If there is a gap in the numbering, it is not a complete binary tree.
(3) Regular binary trees
Regular binary trees are also called strictly binary trees. If any node of a binary tree is either a leaf node or exactly two nonempty subtrees, that is, all branch nodes have a degree of 2 except for leaf nodes with degree 0.
Properties of Binary Trees
Property 1: A nonempty binary tree has at most 2 <sup>i1</sup> (i $\geq$0) nodes on its layer I
Property 5: If a complete binary tree with n nodes is numbered hierarchically from top to bottom (left to right for each layer) from 1 to n, then any node i (i $\leq$I $\leq$n)
 If i = 1, node I is the root and there are no parents. If I > 1, the number of parents is [i/2]
 If 2I $\leq$n, the number of the left child of I is 2i, otherwise there is no left child
 If 2i + 1 $\leq$n, the number of the right child of i is 2i + 1, otherwise there is no right child
Sequential storage structure for binary trees
(1) in a complete binary tree
For a onetomany relationship like trees, using a sequential storage structure is not reasonable, but it is also possible.
For a complete binary tree, the nodes numbered i on the tree are stored in the components labeled i in a onedimensional array, as shown in the following figure
(2) in ordinary binary trees
If you have an ordinary binary tree, you need to now add some empty nodes to make it a full binary tree. The new empty nodes are set to ^as shown in the following figure
(3) In more extreme circumstances
For example, in a rightskewed tree with a depth of k, it only has k nodes, but depending on the previous nature, we know that it is necessary to allocate 2 <sup>k1</sup>memory units, which is obviously a huge waste of storage space, so it seems that sequential storage is more practical when only full binary trees are present.
Binary Tree Chain Storage Structure (Key)
Sequential structure is obviously not very suitable for use, so in practice, we will choose a chain storage structure, chain storage structure, in addition to the need to store its own elements, you also need to set pointers to reflect the logical relationship between nodes, in a binary tree, each node has at most two children, so we set up two pointer fields to point to the left and right children of the node.Children, this structure is called a binary list node (focus on this one)
A common operation in a binary tree is to find the parents of the nodes, and each node can also have an additional pointer field pointing to the parents, a structure called a triplelinked list node
Binary list nodes can be used to form a binary list, as shown in the following figure:
Code representation of tree and binary list
(1) Abstract data types of trees
#ifndef _BINARYTREE_H_ #define _BINARYTREE_H_ #include<iostream> using namespace std; template<class T> class binaryTree { public: // empty virtual void clear()=0; // Null, empty returns true, nonempty returns false virtual bool empty()const=0; //Height of Binary Tree virtual int height() const=0; //Total number of nodes in a binary tree virtual int size()const=0; //Preorder traversal virtual void preOrderTraverse() const=0; //Intermediate traversal virtual void inOrderTraverse() const=0; //Postorder traversal virtual void postOrderTraverse() const=0; //level traversal virtual void levelOrderTraverse() const=0; virtual ~binaryTree(){}; }; #endif
(2) Representation of a binary chain table
Note: We set the Node type and its pointer as private members because it facilitates data encapsulation and hiding, which is not much explained in this article, but rather focuses on algorithm implementation.
#ifndef _BINARYLINKLIST_H_ #define _BINARYLINKLIST_H_ #include "binaryTree.h" #include<iostream> using namespace std; //elemType is the type of element stored for the sequential table template <class elemType> class BinaryLinkList: public binaryTree<elemType> { private: //Binary Chain List Node struct Node { // Pointer to left and right children Node *left, *right; // Node Data Domain elemType data; //nonparameter constructor Node() : left(NULL), right(NULL) {} Node(elemType value, Node *l = NULL, Node *r = NULL) { data = value; left = 1; right = r; } ~Node() {} }; //Root node pointing to binary tree Node *root; //empty void clear(Node *t) const; //Total number of nodes in a binary tree int size(Node *t) const; //Height of Binary Tree int height(Node *t) const; //Number of leaf nodes of a binary tree int leafNum(Node *t) const; //Recursive Pretraversal void preOrder(Node *t) const; //Recursive Ordered Traversal void inOrder(Node *t) const; //Recursive Successive Traverse void postOrder(Node *t) const; public: //Construct an empty binary tree BinaryLinkList() : root(NULL) {} ~BinaryLinkList() {clear();} //Send blank bool empty() const{ return root == NULL; } //empty void clear() { if (root) clear(root); root = NULL; } //Find the total number of nodes int size() const { return size(root); } //Finding the Height of a Binary Tree int height() const { return heigth(root); } //Number of Binary Leaf Nodes int leafNum() const { return leafNum(root); } //Preorder traversal void preOrderTraverse() const { if(root) preOrder(root); } //Intermediate traversal void inOrderTraverse() const { if(root) inOrder(root); } //Postorder traversal void postOrderTraverse() const {if(root) postOrder(root); } //level traversal void levelOrderTeaverse() const; //Nonrecursive Pretraversal void preOrderWithStack() const; //Nonrecursive middle traversal void inOrderWithStack() const; //Nonrecursive postorder traversal void postOrderWithStack() const; }; #endif
Traversal of Binary Trees
(1) Depth first traversal
Concepts: Traversing the nodes of a binary tree along its depth, accessing the branches of a binary tree as deeply as possible, can be divided into three main types: firstorder traversal, middleorder traversal, secondorder traversal, and

Preorder traversal
 Access the root node first, then traverse the left subtree in precedence, and then the left subtree in precedence (rootleftright)

Intermediate traversal
 The left subtree is traversed in middle order, then the root node is accessed, and the right subtree (leftrootright) is traversed in middle order.

Postorder traversal
 Traverse left subtree in order, right subtree in order, and then root node (leftrightroot)
An example is clear:
As an example, the three traversal modes are executed in the following order:
 Preorder traversal: A  B  C  E  F
 Intermediate traversal: B  A  E  C  F
 Postorder traversal: B  E  F  C  A
Let's take the middle order as an example: what does it mean to traverse the left subtree first, then the root node, and then the right subtree (leftrootright) in the middle order?
Mediumorder traversal refers to treating each point as the first node, and then performing the middleorder traversal each time, that is, leftrootright. When the left side is empty, it returns to the parent node that accesses the current node, that is, in the middle, after recording, it accesses the right again.
For example, starting from root node A, visit left child B first, there is no left child B, return to A, visit right side C of A, and then traverse through it in middle order, that is, visit E first, then return to C and then visit F: B  A  E  C  F
First, let's use recursion to implement these three traversals. Recursion gives me the feeling that it's extremely easy to understand and that the code is so concise that it's hardly too fast to implement this algorithm quickly
(1) Pretraversalrecursion
template <class elemType> void BinaryLinkList<elemType>:: preOrder(Node *t) const { if (t) { cout << t > data << ' '; preOrder(t > left); preOrder(t > right); } }
(2) Intermediate traversalrecursion
template <class elemType> void BinaryLinkList<elemType>:: inOrder(Node *t) const { if (t) { preOrder(t > left); cout << t > data << ' '; preOrder(t > right); } }
(3) Postorder traversalrecursion
template <class elemType> void BinaryLinkList<elemType>:: postOrder(Node *t) const { if (t) { preOrder(t > left); preOrder(t > right); cout << t > data << ' '; } }
Tip: You may notice that in the previous definition we defined three methods that are public.
//Preorder traversal void preOrderTraverse() const { if(root) preOrder(root); } //Intermediate traversal void inOrderTraverse() const { if(root) inOrder(root); } //Postorder traversal void postOrderTraverse() const {if(root) postOrder(root); }
This is because all three of the previous recursive methods require a pointer of type Node as an argument, and the root node root pointing to the binary tree is private, which makes it impossible for us to call it with objects of the BinaryLinklist class, so we need to write a common interface function, which is our three above
Although the recursive method is easy to understand, it consumes more space and time, so we can design other algorithms to implement the three traversals above, that is, the idea of using stacks
(1) Pretraversalstack
template <class elemType> void BinaryLinkList<elemType>::preOrderWithStack() const { //Stack in STL stack<Node* > s; //Work Pointer, Initialize to Root Node Node *p = root; //Stack is not empty or p is not empty while (!s.empty()  p) { if (p) { //Access the current node cout << p > data << ' '; //Pointer Push on Stack s.push(); //Working Pointer Points to Left Subtree p = p > left; } else { //Get top stack element p = s.top(); //Unstack s.pop(); //Working Pointer Points to Right Subtree p = p > right; } } }
(2) Intermediate traversalstack
template <class elemType> void BinaryLinkList<elemType>::inOrderWithStack() const { //Stack in STL stack<Node* > s; //Work Pointer, Initialize to Root Node Node *p = root; //Stack is not empty or p is not empty while (!s.empty()  p) { if (p) { //Pointer Push on Stack s.push(); //Working Pointer Points to Left Subtree p = p > left; } else { //Get top stack element p = s.top(); //Unstack s.pop(); //Access the current node cout << p > data << ' '; //Working Pointer Points to Right Subtree p = p > right; } } }
(3) Postorder traversalstack
Postorder traversal is slightly special, with Left and Right flags set to distinguish whether a popup node at the top of the stack returns from the left or right subtree of the top node of the stack
template <class elemType> void BinaryLinkList<elemType>::postOrderWithStack() const { //Define Tags enum ChildType {Left,Right}; //Element type in stack struct StackElem { Node *pointer; ChildType flag; }; StackElem elem; //Stack in STL stack<StackElem> S; //Work Pointer, Initialize to Root Node Node *p = root; while (!S.empty()  p) { while (p != NULL) { elem.pointer = p; elem.flag = Left; S.push(elem); p = p > left; } elem = S.top(); S.pop(); p = elem.pointer; //The left subtree has been traversed if (elem.flag == Left) { elem.flag = Right; S.push(elem); p = p > right; //The right subtree has been traversed } else { cout << p > data << ' '; p = NULL; } } }
There is really no recursive way to understand these three traversals by stack. When learning this part, you can compare a simple diagram to think about it, which can help you better understand the code. You can refer to my example diagram above.
(2) Width first traversal
Widthfirst traversal, also known as widthfirst traversal, or hierarchical traversal, has the idea that nodes are accessed one by one from the root node, top to bottom, and in the same layer, in left to right order
We can use the idea of queues to do this kind of traversal
 Initialize queue, root node enqueue
 Queue is not empty, loop performs the following three steps, otherwise end
 Queue a node while accessing it
 If the node's left subtree is not empty, queue its left subtree
 If the node's right subtree is not empty, queue its right subtree
template <class elemType> void BinaryLinkList<elemType>::levelOrderTeaverse() const { queue<Node* > que; Node *p = root; if (p) que.push(p); while (!que.empty()) { //Take the first element of the queue p = que.front(); //Queue que.pop(); //Access the current node cout << p > data << ' '; //Left Subtree Entry if (p > left != NULL) que.push(p > left); //Right Subtree Entry if (p > right != NULL) que.push(p > rigth); } }
Other Common Operations of Binary Trees
(1) Find the total number of nodes
template <class elemType> int BinaryLinkList<elemType>::size(Node *t) const { if (t == NULL) return 0; return 1 + size(t > left) + size(t > right); }
(2) Calculating the height of a binary tree
template <class elemType> int BinaryLinkList<elemType>::height(Node *t) const { if (t == NULL) return 0; else { int lh = height(t > left); int rh = height(t > right); return 1 + ((lh > rh) ? lh : rh); } }
(3) Number of leaf nodes
template <class elemType> int BinaryLinkList<elemType>::leafNum(Node *t) const { if (t == NULL) return 0; else if ((t > left == NULL) && (t > right == NULL)) return 1; else return leafNum(t > left) + leafNum(t > right); }
(4) Empty
template <class elemType> void BinaryLinkList<elemType>::clear(Node *t) { if (t > left) clear(t > left); if (t > right) clear(t > right); delete t; }
Ending:
If there are any deficiencies or errors in the article, please leave a message to share your thoughts and thank your friends for their support!
If you can help, pay attention to me!If you prefer the way WeChat articles are read, you can focus on my public number
We don't know each other here, but we are working hard for our dreams.
A public number insisting on original development technology articles: Ideal more than 20 days