堆排序複雜度為O(nlogn),需要注意的誤區
阿新 • • 發佈:2019-01-07
本文希望闡述堆排序O(nlogn)的一些關鍵細節,摘錄一篇博文O(n^2)進行比較。
堆排序的特點是優化後的選擇排序,其時間複雜度為O(nlogn),下面第一段程式碼的做法比這個複雜度要高。原因在下文闡述。
堆排序將要排序的物件看做一顆完全二叉樹,資料結構可以用陣列來實現。
初始化建堆過程時間:O(n) 更改堆元素後重建堆時間:O(nlogn)
具體證明可見:http://blog.csdn.net/yuzhihui_no1/article/details/44258297
下面的做法是在建好堆之後,交換堆頂和堆底之後,又執行了重建堆的過程。複雜度應該為O(n^2)。
待比較程式程式碼如下:
package ex;
import java.util.Arrays;
public class Sort {
public static void main(String args[]) {
int []a = new int[] {16,25,34,27,30,5,7,4,41,55};
Sort.heapSort(a);
System.out.println(Arrays.toString(a));
}
static int parent(int i) {
return (i - 1)/2;
}
static int left(int i) {
return 2*i + 1;
}
static int right(int i) {
return 2*i + 2;
}
static void maxHeapfy(int []a,int i,int heapSize) { //陣列a,第i個結點,heapSize是陣列種實際要排序的元素的長度
int left = left(i); //有的時候能夠遞迴到葉子結點,葉子結點無後繼,下面兩個if都注意到了這一點
int right = right(i);
int largest = i;
if(left < heapSize && a[left] > a[largest]) { //
largest = left;
}
if(right < heapSize && a[right] > a[largest])
{
largest = right;
}
if(largest != i) { //把最大值給父結點
a[largest] = a[largest] ^ a[i];
a[i] = a[largest] ^ a[i];
a[largest] = a[largest] ^ a[i];
maxHeapfy(a,largest,heapSize); //發生交換之後還要保證大根堆性質
}
}
static void buildMaxHeap(int []a,int heapSize) {
for(int i = (heapSize-1)/2;i >= 0;i--) { //此處計算非葉子節點時和計算父節點混淆
maxHeapfy(a,i,heapSize); //此處呼叫重建堆的過程增加了時間複雜度
}
}
staticvoid heapSort(int []a) {
for(int i = a.length-1;i > 0;i--) {
buildMaxHeap(a,i+1); //堆的大小從n到2
a[i] = a[0] ^ a[i]; //交換
a[0] = a[0] ^ a[i];
a[i] = a[0] ^ a[i];
}
}
}
//輸出結果://[4, 5, 7, 16, 25, 27, 30, 34, 41, 55]
改進的重建堆的過程
public class HeapSorter implements Sorter{
/* (non-Javadoc)
* @see A4.Sorter#sort(java.lang.Comparable[])
*/
@Override
public void sort(Comparable[] data) {
buildMaxHeap(data,data.length);
}
int parent(int i)
{
return (i-1)/2;
}
int left(int i)
{
return 2*i+1;
}
int right(int i)
{
return 2*i+2;
}
/**
* 將堆排序選出的最大的元素放到陣列的最後位置。
* 下午10:38:26
* 2017年11月29日
* @author city
*/
private void buildMaxHeap(Comparable[] data, int heapSize) {
// First Step build Max-heap
for(int i = heapSize/2-1;i>=0;i--)
{
maxHeapfy(data,i,heapSize);
}
for(int i = data.length-1;i>0;i--)
{
Comparable tmp = data[i];
data[i] = data[0];
data[0] = tmp;
maxHeapfy(data, 0, i);
}
}
/**
* 堆排序演算法核心,建立最大堆。
* 下午10:39:54
* 2017年11月29日
* @author city
*/
private void maxHeapfy(Comparable[] data, int i, int heapSize) {
// TODO Auto-generated method stub
int left = left(i);
int right = right(i);
int largest = i;
if(left<heapSize && data[left].compareTo(data[largest])>0)
{
largest = left;
}
if(right<heapSize && data[right].compareTo(data[largest])>0)
{
largest = right;
}
if(largest!=i)
{
Comparable tmp = data[largest];
data[largest] = data[i];
data[i] = tmp;
maxHeapfy(data, largest, heapSize);
}
}
}
如有錯誤,請指正
比較原文轉載自http://blog.csdn.net/qq_35178267/article/details/78313306#insertcode
如有侵權請聯絡