Data Structure: Binary Tree chain storage, binary tree chain
Data Structure: Binary Tree chain storage (c)
1. Preface
Binary Trees also have two storage methods: array and chain storage. For arrays, we can easily find the subnode and parent node of a node by using the binary tree and subscripts.
The nature of Binary Trees:
1. The I layer of a binary tree has at most 2 I-1 nodes.
2. a k-depth binary tree contains at most 2k-1 nodes.
3. The number of nodes with a moderate number of 2 in any binary tree must be 0. The number of nodes is less than 1.
Description: The degree is 0, which is a leaf node.
4. The depth of the Complete Binary Tree with n nodes is | _ Log2N _ | + 1
5. If a node number in the Complete Binary Tree is I, the left child number is 2i, the right child number is 2i + 1, and the Mother's Day is I/2.
In combination with the 5th attributes, you can easily find any related elements (Parent and Child, brother, etc.) In this Complete Binary Tree.
However, because sequential storage is inherently adapted to a full binary tree, it is not suitable for the following non-full binary tree, so we need to use another storage method-chain storage.
In chained storage, the structure of each node is as follows:
A Data Storage variable corresponds to two pointer fields pointing to the child.
Using the pointer field, we can perfectly store incomplete Binary Trees, as shown below:
2. Code Decomposition
►Based on the above illustration, it is not difficult to give a description of the node.
typedef struct BiTNode{ TElemType data; struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;
►Create and traverse Binary Trees
It is not very easy to create a binary tree, because its creation method also corresponds to three sequences. In fact, I think the process of traversing a binary tree is almost the same as that of creating a binary tree. It is nothing more than assigning values to data during creation, and retrieving data through traversal.
Instead of providing the code, we need to understand:
Note:
1. Leaf nodes are not left and right children, but left and right children are empty.
2. During the manual creation process, we need to determine the number of left and right empty children based on the number of layers!
3. The execution sequence of creation and traversal is the same, so the input and retrieved values are the same.
For example, we need to create a binary tree in the above image in sequence. How should we input it?
AB ## CD ## EF ## G ##
# Here, the left and right nodes of the leaf node are empty.
The Code is as follows:
void createBitree(Bitree &T){ char ch; if((ch=getchar())=='#') T=NULL; else { T=(Bitnode*)malloc(sizeof(Bitnode)); T->data=ch; createBitree(T->Lchild); createBitree(T->Rchild); }}
►Code traversal is basically the same as code creation:
/* First traverse */void preTraverse (Bitree T) {if (T! = NULL) {printf ("% c", T-> data); preTraverse (T-> Lchild); preTraverse (T-> Rchild );}}
/* Sequential traversal */void inorder (Bitree T) {if (T! = NULL) {inorder (T-> Lchild); printf ("% c", T-> data); inorder (T-> Rchild );}}
/* Post-order traversal */void postorder (Bitree T) {if (T! = NULL) {postorder (T-> lchild); postorder (T-> rchild); printf ("% c", T-> data );}}
►The three types of traversal after we enter the characters are as follows:
AB ## CD ## EF ## G ##
ABCDEFG
BADCFEG
BDFGECA
►Finding the depth of a binary tree
Int Depth (Bitree T) {// returns the Depth int d, dl, dr; if (! T) d = 0; else {dl = Depth (T-> Lchild); dr = Depth (T-> Rchild); d = 1 + (dl> dr? Dl: dr);} return d ;}
►Sequence traversal of Binary Trees
Queue <Bitree> TreeQueue; // use the queue TreeQueue. push (tree); // Add the queue Header element to the queue bitp = tree; while (! TreeQueue. empty () // cyclically determines whether the queue is empty. If not, {p = TreeQueue. front (); // get the queue header node and output the queue TreeQueue. pop (); printf ("% c", p-> data); // print the queue element if (p-> Lchild) // if the node has a left node {TreeQueue. push (p-> Lchild); // Add to queue} if (p-> Rchild) // if the node has the right node {TreeQueue. push (p-> Rchild); // Add to queue }}
| Description:
1. algorithm track:
Still used:
Demo:
First, we add ainto the queue. In this case, only region [A] is in the column.
We will pop up the queue for A and add its left and right subtree BC to the queue. At this time, the queue has queue [BC] and print
We will pop up the queue B, which has no sub-tree, and we will not perform any operation. In this case, the queue has a forward [C], and the ABC is printed.
We will pop up the C-out queue and add its left and right subtree DE to the queue. In this case, there is a forward [DE] in the queue and the ABC is printed.
We will output "D" to the pop-up queue, which has no sub-tree and we will not perform any operations. In this case, the queue has queue [E] And the ABCD is printed.
We will pop up the E-out queue and add its left and right subtree FG to the queue. In this case, there is a forward [FG] in the queue and print the ABCDE
The F-out pop-up queue has no sub-tree, and we do not perform any operations. In this case, the queue has a forward [G] and the ABCDEF is printed.
We will pop up the G-out queue, which has no sub-tree, and we will not perform any operation. In this case, the queue has limit [null], and the ABCDEFG is printed.
Conclusion:
Based on the trajectory, it is not difficult to find that the queue is the basis of sequence traversal, because it ensures that the upper-layer elements first added to the queue will be mandatory, and the lower-layer elements added to the queue will give priority to the queue.
2. This code will cause problems because we use the queue in the C ++ standard template library. Therefore, we need to add the header file
# Include <queue> and use the namespace using namespace std ;.
3. the most important thing for us to treat the data structure is to understand and use it. Implementing it only helps us to understand it. We do not need to repeat the wheel. In future algorithms, we will reference the standard template library as much as possible.