Document directory
- Summary of binary sorting:
Summary of binary sorting:
The binary sorting tree is a dynamic query table and a Complete Binary Tree. Its nature is:
Or an empty tree, or meet the following requirements:
1. If the left subtree is not empty, the values of all nodes in the left subtree are smaller than those of the root node.
2. If the right subtree is not empty, the values of all nodes in the right subtree are greater than those of the root node.
3. Its left and right subtree is also a binary search tree. We can see that the Binary Search Tree is a recursive definition (the tree itself is a recursive definition .)
As shown in, it is a simple binary search tree:
Based on the definition of the binary sorting tree, we know that if the middle order is traversed, the result must be an ascending sequence. (Counterproof ).
The binary sorting tree is used for search. The process is similar to binary search: first, the root node is compared with the key to be searched. If it is equal, the root node is returned. Otherwise, the Child tree on the left (right) is recursively searched based on the corresponding size relationship until the search is successful or the query fails.
The search algorithm is described as follows:
// Find the node * bstreesearch (bstree T, int K) with the value of K in the binary search tree T) {If (t = NULL | K = T-> key) {return t;} If (k <t-> key) {return bstreesearch (t-> lchild, k) ;}else {return bstreesearch (t-> rchild, k );}}
The binary sorting tree acts as a "dynamic query table ". The basic operations to be implemented include:
1. node * bstreesearch (bstree T, int K) ==> search for a node with a specific value equal to K 2. node * bstreeminimum (bstree t) ==> search for the minimum value 3. node * bstreemaxmum (bstree t) ==> find the maximum value 4. void bstreeinsert (bstree & T, int K) ==> Insert a new node with a value of K 5. node * bstreedelete (bstree & T, node * z) ==> delete a node and return the deleted node. Of course, to achieve these operations, we can also (not required) 6. node * bstreesuccessor (node * X) => Find the successor node of the node 7. node * bstreeprecessor (node * X) => search for the frontend node of a node
The following is an analysis summary:
1. Search. See the search algorithm above. I will not go into details. 2. Find the minimum value.
Because of the nature of the binary search tree. The node with the smallest value must be the leftmost node. We walked along the root node to the far left. The minimum node is found. (This can also be clearly seen from the diagram of the Binary Search Tree)
The algorithm is concise and does not need to be explained as follows:
// Find the minimum node of the binary search tree * bstreeminimum (bstree t) {node * x = T; while (X-> lchild! = NULL) {x = x-> lchild;} return X ;}
3. Find the maximum value.
Corresponds to the minimum search value. The node with the largest value must be the rightmost node. We walked along the root node to the rightmost. The largest node is found.
// Find the maximum node of the binary search tree * bstreemaxmum (bstree t) {node * x = T; while (X-> rchild! = NULL) {x = x-> rchild;} return X ;}
4. Skip Binary Tree insertion and deletion. First, let's take a look at how to find the frontend and successor of a node.
A. node precursor: According to the definition, the precursor node is a node located at the front of the node when traversing the binary search tree in a central order. There are several situations:
<1>. If the node has a left subtree. The precursor must be in the left subtree and is the largest node of the Left subtree.
(The precursor of 45 nodes is the maximum value of the Left subtree 37 ):
<2> the node does not have a left subtree. The node precursor should be the direct precursor for traversing the binary search tree in the middle order. Who is the pioneer? See: Which node is the precursor of node 24 (find the first node earlier than 24 )?
We can find it like this, and the pointer keeps moving up (that is, node * Y = x-> parent) until X is the right subtree of Y (because if it is the left subtree, the parent node can only be located behind the node, and cannot be a precursor ).
The algorithm is as follows:
// Find the node * bstreeprecessor (node * X) of a node in the binary tree {If (X-> lchild! = NULL) return bstreemaxmum (X-> lchild); node * Y = x-> parent; while (y! = NULL & X = Y-> lchild) {x = y; y = Y-> parent;} return y ;}
B. successor of a node: as defined, a successor node is a node located right behind the node when traversing the binary search tree in a central order. There are several situations:
<1>. If the node has a right subtree. The successor must be in the right subtree, and it is the smallest node of the Left subtree.
<2> If the node does not have a right subtree. Similar to the search precursor. The pointer keeps moving up (that is, node * Y = x-> parent) until X is the left subtree of Y (because if it is the right subtree, the parent node can only be located in the front of the node, and cannot be a successor ).
The algorithm is as follows:
// Search for the node * bstreesuccessor (node * X) of a node in the tree. {If (X-> rchild! = NULL) return bstreeminimum (X-> rchild); node * Y = x-> parent; while (y! = NULL & X = Y-> rchild) {x = y; y = Y-> parent;} return y ;}
5. Insert a binary search tree.
The process of building a binary search tree is the process of constantly searching for inserts and then inserting new nodes. Insert/delete is a prerequisite for dynamic search.
The Insert Process of the Binary Search Tree is: Determine the insert position and insert a new node. The key is: how to determine the insert position. In fact, the process of determining the insert position is similar to that of the Binary Search Tree.
First, compare it with the root. If it is smaller than the root, it is located in the left subtree; otherwise, it is located in the right subtree. Record the parent node of a node during the search process. Once the node is found to be empty, the parent node is the parent node of the node to be inserted (of course, if the parent node is empty, the tree is empty, in this case, you only need to simply make the root node equal to the new node inserted ). Then you can determine whether the left or right subtree is used.
The Code is as follows:
// Insert a node into the binary search tree. Void bstreeinsert (bstree & T, int K) {node * Y = NULL; node * x = T; node * z = new node; Z-> key = K; z-> lchild = z-> parent = z-> rchild = NULL; while (X! = NULL) {Y = x; If (k <X-> key) x = x-> lchild; else x = x-> rchild;} Z-> parent = y; if (y = NULL) {T = z;} else if (k <Y-> key) Y-> lchild = z; else y-> rchild = z ;}
6. Delete the binary search tree.
This is the difficulty of binary tree search. If you do not draw a picture, it is difficult to understand.
Note that deleting a node can be divided into several situations:
1. If the node does not have a left subtree or a right subtree, you can simply delete it.
2. If the node has a left subtree but no right subtree. After the node is deleted, change the left subtree to the left subtree of the parent node.
3. Similar to 2. If the node has a right subtree but no left subtree. After the node is deleted, change the right subtree to the right subtree of the parent node.
4. If the node has a left subtree or a right subtree. A little effort. You can choose to delete the frontend or successor of a node. Record the parent node during the process of searching the parent node or its successor. After deleting the precursor or successor node, connect to the left and right subtree of the original or successor node.
The algorithms provided in the introduction to algorithms are as follows:
Node * bstreedelete (bstree & T, node * z) {node * X, * Y; If (Z-> lchild = NULL | Z-> rchild = NULL) {Y = z; // y node is the final deleted node} else {Y = bstreesuccessor (z);} If (Y-> lchild! = NULL) {x = Y-> lchild;} else {x = Y-> rchild;} If (X! = NULL) {X-> parent = Y-> parent;} If (Y-> parent = NULL) {T = x ;} else if (y = Y-> parent-> lchild) {Y-> parent-> lchild = x;} else {Y-> parent-> rchild = x ;} if (y! = Z) {z-> key = Y-> key; // node Y is the final deleted node if it is not the Z Node itself. Copy the value of the deleted node} return y ;}
You can also perform the deletion process based on these situations. It may be easier to understand.
The complete test code is as follows:
/* Complete source code implementation of the binary sorting tree. * Reference: 1. Yan Weimin = Data Structure * 2 Introduction to algorithms pseudo code * 3. http://www.wutianqi.com /? P = 2430) */# include <iostream> using namespace STD; typedef struct node {int key; node * lchild, * rchild, * parent;} node, * bstree; // find the minimum node of the binary search tree * bstreeminimum (bstree t) {node * x = T; while (X-> lchild! = NULL) {x = x-> lchild;} return X;} // find the maximum node of the binary search tree * bstreemaxmum (bstree t) {node * x = T; while (X-> rchild! = NULL) {x = x-> rchild;} return X;} // search for a node that is equal to a value. Recursive version node * bstreesearch (bstree T, int K) {If (t = NULL | K = T-> key) {return t ;} if (k <t-> key) {return bstreesearch (t-> lchild, k);} else {return bstreesearch (t-> rchild, k );}} // search for the node * bstreesuccessor (node * X) of a node in the tree. {If (X-> rchild! = NULL) return bstreeminimum (X-> rchild); node * Y = x-> parent; while (y! = NULL & X = Y-> rchild) {x = y; y = Y-> parent;} return y ;} // find the node * bstreeprecessor (node * X) of a node in the binary tree {If (X-> lchild! = NULL) return bstreemaxmum (X-> lchild); node * Y = x-> parent; while (y! = NULL & X = Y-> lchild) {x = y; y = Y-> parent;} return y ;}// insert a node into the binary search tree. Void bstreeinsert (bstree & T, int K) {node * Y = NULL; node * x = T; node * z = new node; Z-> key = K; z-> lchild = z-> parent = z-> rchild = NULL; while (X! = NULL) {Y = x; If (k <X-> key) x = x-> lchild; else x = x-> rchild;} Z-> parent = y; if (y = NULL) {T = z;} else if (k <Y-> key) Y-> lchild = z; else y-> rchild = z ;} node * bstreedelete (bstree & T, node * z) {node * X, * Y; If (Z-> lchild = NULL | Z-> rchild = NULL) {Y = z;} else {Y = bstreesuccessor (z);} If (Y-> lchild! = NULL) {x = Y-> lchild;} else {x = Y-> rchild;} If (X! = NULL) {X-> parent = Y-> parent;} If (Y-> parent = NULL) {T = x ;} else if (y = Y-> parent-> lchild) {Y-> parent-> lchild = x;} else {Y-> parent-> rchild = x ;} if (y! = Z) {z-> key = Y-> key;} return y;} void visit (node * X) {If (X! = NULL) {printf ("% d \ n", X-> key) ;}} void intraverse (bstree t) {If (T! = NULL) {intraverse (t-> lchild); visit (t); intraverse (t-> rchild) ;}} int main () {int m; bstree T = NULL; while (scanf ("% d", & M )! = EOF) {bstreeinsert (T, m); printf ("sequential traversal in the binary search tree:"); intraverse (t); printf ("\ n ");} printf ("after the left node is deleted:"); bstreedelete (t, t-> lchild); intraverse (t );}
Performance: the query time of the Binary Search Tree is proportional to the depth of the tree, that is, the log (n) order of magnitude. In the worst case, the binary search tree may degrade to a linear linked list, the query time of the binary query tree is O (n), which is the same as that of the sequence table.