Number less than or equal to the number in the heap sorting program
A bug occurs during heap sorting. It takes a long time for debugging to find the cause.Less than or equalThe boundary in recursion is not fully considered. The code is written in java and analyzed. First, there are a lot of programs on the Internet that use code greater than the number control boundary:
Import java. util. *; public class MaxHeap {public static int [] heapSort (int [] A, int n) {// write code here MakeMaxHeap (A, n-1); System. out. println ("build complete"); for (int I = n-1; I> = 0; I --) {// continuously reduce the heap size swap (A, 0, I ); for (int ii = 0; ii <7; ii ++) {System. out. print (A [ii] + ",");} System. out. println ("swap" + "A [0]" + "<->" + "A [I]:" + I); MaxHeapFixUp (A, 0, I );} return A;} public static void MakeMaxHea P (int [] a, int heapsize) {for (int I = (heapsize-1)/2; I> = 0; I --) {MaxHeapFixUp (a, I, heapsize) ;}}// adjust the heapsize from the I node. The heapsize is the heap length and starts from 0. The subnode of the I node is calculated as 2 * I + 1, 2 * I + 2 public static void MaxHeapFixUp (int [] a, int I, int heapsize) {int lchild = 2 * I + 1; int rchild = 2 * I + 2; int largest =-1; if (lchild
Heap sorting result: 0, 1, 2, 3, 4, 5, 6 is correct (some intermediate output results are not given)
My code is referring to the pseudocode in "Introduction to algorithms". In the MaxHeapFixUp function, the red font is less than or equal
If (lchild <= heapsize & a [lchild]> a [I]) {// lchild <= heapsize why is an error? Largest = lchild;} else {largest = I;} if (rchild <= heapsize & a [rchild]> a [largest]) {largest = rchild ;}
The result is incorrect: 5, 2, 3, 0, 4, 1, 6,
The following is the pseudocode in the introduction to algorithms (the first version, P75). We can see that this is also used.Less than or equal
At that time, I wrote according to the idea in "Introduction to algorithms", so I didn't know it was a problem with the number less than or equal. I had to output the intermediate steps to find the cause. The input array is already a large root heap, so there is no problem in the heap creation process. After the heap is created, the top element of the heap should be exchanged with the elements at the end of the array. At the same time, the heap length should be reduced by one and the remaining heap should be adjusted. The following output reflects the heap adjustment process:
Build complete
0, 5, 4, 3, 2, 1, 6, swap A [0] <-> A [I]: 6
5, 0, 4, 3, 2, 1, 6, swap largest: 1 <-> I: 0
5, 3, 4, 0, 2, 1, 6, swap largest: 3 <-> I: 1
5, 3, 4, 0, 2, 1, 6, heapsize: 6
5, 3, 4, 0, 2, 1, 6, heapsize: 6
5, 3, 4, 0, 2, 1, 6, heapsize: 6
1, 3, 4, 0, 2, 5, 6, swap A [0] <-> A [I]: 5
4, 3, 1, 0, 2, 5, 6, swap largest: 2 <-> I: 0
4, 3, 5, 0, 2, 1, 6, swap largest: 5 <-> I: 2
4, 3, 5, 0, 2, 1, 6, heapsize: 5
4, 3, 5, 0, 2, 1, 6, heapsize: 5
4, 3, 5, 0, 2, 1, 6, heapsize: 5
The first line of the yellow part indicates that the execution is performed.HeapSortFunctionSwapStatement.5Elements at the end of the array1Switch (at this time, 6 is no longer heap, and 1 is the last number)
The second line indicates executionMaxHeapFixUp (int [] a, int I, intHeapsize)FirstI = 0The node is adjusted, and the maximum value is found in node 0 and its sub-nodes 1 and 2 and placed at the root node 0. Obviously, here A [2] = 4 is the largest of A [0], A [1], A [2], so A [0] is exchanged with A [2. The array is changed from 1, 3, 4, 0, 2, 5, 6 to 4, 3, 1, 0, 2, 5, 6. This step is correct.
The third line is to continue execution.MaxHeapFixUp (int [] a, int I, intHeapsize)The result after the function, because A [2] is A root node and its value has changed in the previous step, you need to re-adjust the heap with A [2] as the root. The children of A [2] are A [5] and A [6]. It seems that we want to continue to compare A [2], A [5], find the maximum value of A [6] and exchange it with A [2. But the problem arises. In the output of the first line, we put A [5] = 5 to the end of the array, that is, we discharged it from the heap, that isAfter that, A [5] cannot be involved in heap operations.
However, unfortunately, in the code, I wrote
If (Lchild <= heapsize& A [lchild]> a [I])
In this stepLchild = 5, heapsize = 5Then, the value of A [5] is exchanged with A [2] to obtain 4, 3, 5, 0, 2, 1, 6.
Therefore, the heap range is extended after the number is changed to less than or equal to, and the number of the newly removed heap (the number has been partially sorted) is pulled in again, in this way, the sorted order is disrupted, and the result is wrong.
Solution:
1. If you change the non-equal sign to the minor sign
If (Lchild & A [lchild]> a [I])
If (Rchild & A [rchild]> a [largest])
This problem will not occur.
2. In order to maintain consistency with the introduction to algorithms and make it easy to understand, the number smaller than or equal to can be retained, but must be modified.HeapsizeInHeapSortFunction willMaxHeapFixUp (A, 0, I );ChangeMaxHeapFixUp (A, 0, I-1 );
Public static int [] heapSort (int [] A, int n) {// write code here MakeMaxHeap (A, n-1); System. out. println ("build complete"); for (int I = n-1; I> = 0; I --) {// continuously reduce the heap size swap (A, 0, I ); for (int ii = 0; ii <7; ii ++) {System. out. print (A [ii] + ",");} System. out. println ("swap" + "A [0]" + "<->" + "A [I]:" + I); MaxHeapFixUp (A, 0, I-1 );} return ;}
This is actually more reasonable, because the first execution in the heapSort FunctionSwap (A, 0, I)A [0] = 6 and A [n-1] = 1 have been swapped, that is, the heap top element A [0] = 6 has been removed from the heap,At this point the heap size should be 6, in the array subscript is 1 to 5, I-1 = 5.
In Introduction to algorithms, pseudocode assumes that the array subscript starts from 1, while the actual program subscript starts from 0. Therefore, although the array length is 7, however, the value of heapsize is decreased from 6, so we need to useI-1InsteadI.
Finally, we will send the modified Code as a whole. Pay attention to the red part as the difference between the codes that have just been pasted in this article.
Import java. util. *; public class MaxHeap {public static int [] heapSort (int [] A, int n) {// write code here MakeMaxHeap (A, n-1); System. out. println ("build complete"); for (int I = n-1; I> = 0; I --) {// continuously reduce the heap size swap (A, 0, I ); for (int ii = 0; ii <7; ii ++) {System. out. print (A [ii] + ",");} System. out. println ("swap" + "A [0]" + "<->" + "A [I]:" + I); MaxHeapFixUp (A, 0, I-1 );} return A;} public static void MakeMaxH Eap (int [] a, int heapsize) {for (int I = (heapsize-1)/2; I> = 0; I --) {MaxHeapFixUp (a, I, heapsize) ;}/// start from the I node. heapsize indicates that the total number of nodes starts from 0. The subnode of the I node is calculated as 2 * I + 1, 2 * I + 2 public static void MaxHeapFixUp (int [] a, int I, int heapsize) {int lchild = 2 * I + 1; int rchild = 2 * I + 2; int largest =-1; if (lchild <= heapsize & a [lchild]> a [I]) {// lchild <= heapsize why is an error? Largest = lchild;} else {largest = I;} if (rchild <= heapsize & a [rchild]> a [largest]) {largest = rchild;} if (largest! = I) {swap (a, largest, I); for (int ii = 0; ii <7; ii ++) {System. out. print (a [ii] + ",");} System. out. println ("swap" + "largest:" + largest + "<->" + "I:" + I); MaxHeapFixUp (a, largest, heapsize ); // The heap changes. You need to call it recursively to adjust the heap} for (int ii = 0; ii <7; ii ++) {System. out. print (a [ii] + ",");} System. out. println ("heapsize:" + heapsize);} public static void swap (int [] a, int I, int j) {int temp; temp = a [I]; a [I] = a [j]; a [j] = temp;} public static void main (String [] args) {int [] A = {6, 5, 4, 3, 2, 1, 0}; // {0, 1, 2, 3, 4, 5, 6}; int [] a = heapSort (A, 7); System. out. println ("heap sorting result:"); for (int I = 0; I <7; I ++) System. out. print (a [I] + ","); System. out. println ("");}}