堆排序

堆排序的核心是创建最大堆,然后对堆进行调整。整个算法的实现比较简单,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//调整堆的分支结构--核心方法,注意这里的对于heapsize参数的设计,有的人会觉得这里完全可以通过heap进行计算求得,
//为什么一定要在参数中出现呢?我们看到后面就知道了。
public  static  void  maxHeap( int [] heap,  int  heapsize,  int  index) {
     int  left = left(index);
     int  right = right(index);
     int  largest = index;
     //得到最大节点的下标(index)
     if  (left < heapsize && heap[left] > heap[index]) {
         largest = left;
     }
     if  (right < heapsize && heap[right] > heap[largest]) {
         largest = right;
     }
     if  (index != largest) {
         swap(heap, index, largest);
         //继续向下调整堆,直到符合最大堆的要求
         maxHeap(heap, heapsize, largest);
     }
}
 
public  static  void  buildMaxHeap( int [] array) {
     if  (array ==  null  || array.length <  1 ) {
         return ;
     }
     for  ( int  i = array.length /  2 ; i >=  0 ; i--) {
         //构建最大堆。。。只构建到一半是因为后面的都被动调整过l,不需要再次构建
         maxHeap(array, array.length, i);
     }
}
 
public  static  void  heapSort( int [] array) {
     if  (array ==  null  || array.length <=  1 ) {
         return ;
     }
     buildMaxHeap(array);
     //此时已经建立好最大堆了
     for  ( int  i = array.length -  1 ; i >=  1 ; i--) {
         swap(array,  0 , i);
         //因为最大堆建好之后要进行一步交换操作,这是如果把需要排序的数组长度作为参数传进去的话更利于调整控制。
         //这也就是为什么在开始的时候会有参数设置这个疑问。
         maxHeap(array, i,  0 );
     }
}
 
public  static  void  swap( int [] array,  int  i,  int  j) {
     int  temp = array[i];
     array[i] = array[j];
     array[j] = temp;
}
 
public  static  int  left( int  i) {
     return  2  * i;
}
 
public  static  int  right( int  i) {
     return  2  * i +  1 ;
}

最优时间复杂度:O(nlog(n))


平均时间复杂度:O(nlog(n))


最坏时间复杂度:O(nlog(n))


平均空间复杂度:O(1)

堆排序的时候也不停地有元素交换操作,所以堆排是不稳定的。

你可能感兴趣的:(堆排序)