Transferred from: http://blog.csdn.net/sqx2011/article/details/8241734
Both the Victor tree and the loser tree are completely binary trees, a variant of the tree-shaped selection sort. Each leaf node is equivalent to one player, each of which is equivalent to a match, and each layer is equivalent to a round of matches.
The difference is that the middle node of the Victor Tree records the mark of the winner, while the loser's mark is recorded in the middle node of the loser tree.
The winner tree and the loser tree can find the maximum value in log (n) time. When the value of any one leaf node changes, it is possible to find the maximum value quickly using the information from the middle node. Often used in the K-way merge sort.
First, the Victor Tree
One advantage of the victor Tree is that if a player's value changes, it is easy to modify the winner tree. Simply modify the binary tree along the path from the node to the root node without changing the results of the other races.
Fig. 1
Fig.1 is an example of a victor tree. The specified value is the lesser of the winner.
- B3 PK B4,b3 wins B4 negative, internal node Ls[4] value is 3;
- B3 PK B0,b3 wins B0 negative, internal node ls[2] value is 3;
- B1 PK b2,b1 wins B2 negative, internal node ls[3] value is 1;
- B3 PK B1,b3 wins B1 negative, internal node Ls[1] value is 3.
When Fig. The value of the leaf node B3 in 1 becomes 11 o'clock, and the reconstructed tree is like fig. As shown in 2.
- B3 PK B4,b3 wins B4 negative, internal node Ls[4] value is 3;
- B3 PK B0,b0 wins B3 negative, internal node ls[2] value is 0;
- B1 PK b2,b1 wins B2 negative, internal node ls[3] value is 1;
- B0 PK B1,b1 wins B0 negative, internal node ls[1] value is 1.
Fig. 2
By using the Victor tree to sort n nodes, it is similar to build the victor tree and the building heap, except that the winner tree has only the leaf node to store the data, and the middle node records the relationship between the leaf nodes.
LEAVES[N+1]: A total of n leaf nodes, storing subscript from 1 to n
Successtree[n]: Stores intermediate nodes, storing subscripts from 1 to n-1
For successtree data from n-1 to 1, adjust the values of the internal nodes according to the winning strategy, and finally get a winner tree
The subscript of the champions node is stored in successtree[1], when a sort operation is performed, the value of the leaf node is printed out and replaced with a value that is larger than all the values in the leaf node, and then the tree is adjusted. The winner tree adjustment is from the leaf node to the root node of the bottom-up adjustment, each time compared to the parent node of the child node, and the winner of the next sign stored in the parent node.
[CPP]View Plaincopy
- #include <stdio.h>
- #define K 10
- #define MAX 65535
- int leaves[k+1];
- int successtree[k];
- / * Adjust for individual internal nodes * /
- void Adjust (int i)
- {
- int m,n;
- if (2 * i < K)/ * Get it's left child node * /
- m = successtree[2 * I];
- Else
- m = 2 * i-k + 1;
- if (2*i+1<k)/ * Get It's right child node * /
- n = successtree[2*i+1];
- Else
- n = 2 * i +-K + 2;
- Successtree[i] = Leaves[m] > leaves[n]? n:m; / * Make a decision * *
- }
- / * Initialize leaf nodes and make heap-like adjustments to internal nodes * /
- void Inittree ()
- {
- For (int i=1;i<k+1;i++)
- scanf ("%d", &leaves[i]);
- For (int i=k-1;i>0;i--)
- adjust (i);
- }
- / * Make adjustments to the winner tree from the bottom up * /
- void Adjusttoroot (int i)
- {
- int parent = (i + K-1)/2; / * All on the path from the current node to the root node
- * Node Adjustment */
- While (parent>0)
- {
- adjust (parent);
- parent = PARENT/2;
- }
- }
- int main ()
- {
- Freopen ("in","R", stdin);
- Inittree ();
- for (int i=1;i<k+1;i++)/ * Each time the champion node is replaced with the maximum value, and the tree
- * Make adjustments and eventually get the sequence in ascending order */
- {
- printf ("%d", leaves[successtree[1]]);
- Leaves[successtree[1]]=max;
- Adjusttoroot (successtree[1]);
- }
- return 0;
- }
Second, the loser tree
The loser tree is a variant of the victor Tree. In the loser tree, the loser who uses the parent node to record the left and right sub-nodes of the game, and lets the winner participate in the next round of the game. The root node of the loser Tree records the loser and needs to add a knot to record the winner of the game. Using the loser tree can simplify the process of refactoring.
Fig. 3
Fig. 3 is a loser tree. The number of people defeated.
- B3 PK B4,b3 wins B4 negative, internal node Ls[4] value is 4;
- B3 PK B0,b3 wins B0 negative, internal node ls[2] value is 0;
- B1 PK b2,b1 wins B2 negative, internal node ls[3] value is 2;
- B3 PK B1,b3 wins B1 negative, internal node ls[1] value is 1;
- On the root node ls[1] added a node ls[0]=3, record the last winner.
The loser tree refactoring process is as follows:
- Match the new node that enters the selection tree with its parent node: The loser is stored in the parent node, and the winner is compared to the parent node of the upper level.
- The race continues along the path to the root node until ls[1]. Store the loser in the node ls[1], and the winner is stored in the ls[0].
Fig. 4
Fig. 4 is the re-composition of the loser tree when B3 becomes 13 o'clock.
Note that the reconstruction of the loser tree is not the same as that of the victor Tree, and the reconstruction of the loser tree only needs to be compared with its parent node, while the victor tree needs to be compared with the sibling nodes. Contrast Fig. 3, B3 and node ls[4] of the original value comparison, ls[4] stored in the original value is the node 4, that is, B3 and B4 comparison, B3 negative B4 wins, then modify the value of ls[4] is the node 3. In the same way, keep playing along the root node until the end.
The loser tree is often used for multiple external sorting, and for K's already sequenced files, it is merged into an ordered file. The leaf node of the loser tree is the data node, 22 groupings, the internal node records the "loser" in the left and right subtree, the winner is passed up to the root node, if the winner is the lesser of two, then the root node records the loser in the last comparison, that is, the second small number, and a variable to record the smallest number. After the minimum value is output, replace the value of the minimum node with a new value (when the file is merged, if the file has been read, can be replaced with an infinite number), then maintain the loser tree, from the updated node up, once compared to the parent node, the loser updates, the winner continues to compare.
Note: The entire tree needs to be completely rebuilt when the number of leaf nodes changes.
Compare the performance of the loser Tree and heap
Loser tree in maintenance, the number of comparisons is logn+1, the loser tree from the bottom of the maintenance, each on a layer, only need to compare with the parent, and the heap is from the top down maintenance, each layer needs and left and right sub-nodes are compared, need to compare two times, from this angle, the loser tree better than the heap, but the loser tree Must be a path from the leaf node to the root node, while the heap maintenance may stop at a certain level in the middle, so that the loser tree, although each layer is less than the heap comparison, but the heap comparison of the number of layers may be less.
Find the largest k from the N number, and use the heap and the loser tree respectively to achieve
Heap implementation: Maintenance of a small heap size k, each to a number and heap top comparison, if the heap is smaller than the top, directly discard, or replace the heap top, maintenance heap, until the n number is processed, the time complexity of O (NLOGK)
Loser Tree implementation: When using an array to achieve the loser tree, maintenance of a leaf node number k of the loser tree, note is the number of leaf nodes and not the number of nodes, the number of smaller wins, the topmost preservation is the lowest value of the leaf node, each to a number and the smallest comparison, if the minimum value is small, directly discarded, Otherwise, replace the minimum value of the node value, from the bottom up to maintain the loser tree, the last K-leaf node is stored in all the number of the largest k, time complexity O (NLOGK)
When using an array to implement the loser tree, the loser tree uses twice times as much memory space as only the leaf nodes store the data.
Within the full tree, the number of nodes with a degree of 2 is the number of leaf nodes minus one, so the array size used is 2k-1, and if the maximum value is also stored in the array, the required array size is 2k
The structure of the loser tree
Idea: First constructs an empty loser tree, and then leaves the leaf node one by inserting the loser tree, from the bottom upward continuously adjusts, maintains the internal node to save is the loser's node number, the winner has been continuously upward compares, finally obtains a qualified loser tree.
LEAVES[K+1]: The number of leaf nodes is K, subscript from 1 to K, subscript 0 stores a minimum value, used to initialize the loser tree
LOSERTREE[K]: Champions node is stored in subscript 0, subscript 1 to K-1 storage internal node
[CPP]View Plaincopy
- int losertree[k]; / * Store The median node value, store the Champions node at subscript 0 * /
- int leaves[k+1]; / * Store the leaf node value starting with subscript 1, and store a minimum node at subscript 0 * /
- void adjust (int i)
- {
- int parent= (i+k-1)/2; / * Find the subscript for the parent node * /
- While (parent>0)
- {
- if (Leaves[i]>leaves[losertree[parent]])
- {
- int temp=losertree[parent];
- Losertree[parent]=i;
- / * I point to the winner * /
- i= temp;
- }
- parent = PARENT/2;
- }
- Losertree[0]=i;
- }
- void Initlosertree ()
- {
- int i;
- For (i=1;i<k+1;i++)
- scanf ("%d", &leaves[i]);
- Leaves[0]=min;
- For (int i=0;i<k;i++)
- losertree[i]=0;
- For (int i=k;i>0;i--)
- adjust (i);
- }
(go) loser Tree and Victor Tree---array implementation