堆排序

堆积排序(Heapsort)是指利用堆积树(堆)这种资料结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O(nlog2n) ,堆排序的堆序的平均性能较接近于最坏性能。

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(1)用大根堆排序的基本思想

① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区

② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key

③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。

……

直到无序区只有一个元素为止。

(2)大根堆排序算法的基本操作: 

① 初始化操作:将R[1..n]构造为初始堆;

② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。

注意: 

①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。

②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。

 1 public class HeapSortTest {  
 2   
 3     public static void main(String[] args) {  
 4         int[] data5 = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };  
 5         print(data5);  
 6         heapSort(data5);  
 7         System.out.println("排序后的数组:");  
 8         print(data5);  
 9     }  
10   
11     public static void swap(int[] data, int i, int j) {  
12         if (i == j) {  
13             return;  
14         }  
15         data[i] = data[i] + data[j];  
16         data[j] = data[i] - data[j];  
17         data[i] = data[i] - data[j];  
18     }  
19   
20     public static void heapSort(int[] data) {  
21         for (int i = 0; i < data.length; i++) {  
22             createMaxdHeap(data, data.length - 1 - i);  
23             swap(data, 0, data.length - 1 - i);  
24             print(data);  
25         }  
26     }  
27   
28     public static void createMaxdHeap(int[] data, int lastIndex) {  
29         for (int i = (lastIndex - 1) / 2; i >= 0; i--) {  
30             // 保存当前正在判断的节点  
31             int k = i;  
32             // 若当前节点的子节点存在  
33             while (2 * k + 1 <= lastIndex) {  
34                 // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点  
35                 int biggerIndex = 2 * k + 1;  
36                 if (biggerIndex < lastIndex) {  
37                     // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex  
38                     if (data[biggerIndex] < data[biggerIndex + 1]) {  
39                         // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值  
40                         biggerIndex++;  
41                     }  
42                 }  
43                 if (data[k] < data[biggerIndex]) {  
44                     // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k  
45                     swap(data, k, biggerIndex);  
46                     k = biggerIndex;  
47                 } else {  
48                     break;  
49                 }  
50             }  
51         }  
52     }  
53   
54     public static void print(int[] data) {  
55         for (int i = 0; i < data.length; i++) {  
56             System.out.print(data[i] + "\t");  
57         }  
58         System.out.println();  
59     }  
60   
61 }  

——使记录序列按关键字非递减有序排列,则在堆排序的算法中先建立一个“大顶堆”,即先选得一个关键字为最大的记录,并与序列中最后一个记录交换,然后对序列中前n-1记录进行筛选,重新将它调整为一个“大顶堆”,如此反复直至排序结束。

 1 import java.util.*;
 2  
 3 public class HeapSort {
 4     public int[] heapSort(int[] A, int n) {
 5         // write code here
 6         for(int i=n/2; i>=0; i--){
 7             heapAdjust(A,i,n);
 8         }
 9          
10         for(int i=n-1;i>0;i--){
11             swap(A,0,i);
12             heapAdjust(A,0,i);
13         }
14         return A;
15     }
16      
17     void heapAdjust(int[] A,int index,int length){
18         int childLeft;
19         int temp = A[index];
20         for( ;index*2+1 < length;index = childLeft){
21             childLeft = index*2+1;
22             if(childLeft !=length-1 && A[childLeft] < A[childLeft+1]){
23                  childLeft++;
24             }
25             if(temp > A[childLeft]){
26                 break;
27                  
28             }                
29             else {
30                 A[index] = A[childLeft];
31                 index = childLeft;
32             }           
33         }
34          A[index] = temp;
35          
36     }
37      
38     static void  swap(int[] A,int m,int n){
39         int temp = A[m];
40         A[m] = A[n];
41         A[n] = temp;
42     }
43 }

 

posted @ 2017-04-06 17:22  临江仙zhe  阅读(127)  评论(0)    收藏  举报