堆排序基本介紹
堆排序用到了完全二叉樹的順序儲存結構(即陣列),所以順序儲存並不是完全無用,在這裡會發揮大作用。
tips:一定要理解大頂堆、小頂堆、完全二叉樹以及完全二叉樹的順序儲存結構才能理解堆排序,這個是前提喲!!!
圖1:大頂堆示例
圖2:小頂堆示例
堆排序基本思路
以公升序排序來講,先將陣列arr(0 ~ arr.length-1)調整成乙個堆。
1.1 怎麼調整?從0~arr.length-1的元素中的最後乙個非葉子節點開始調整,這個葉子節點的下標是arr.length/2-1,設為x;
1.2 這個葉子節點的左子節點的下標2*x+1,設為leftchild;右子節點的下標識2*x+2,設為rightchild。然後比較arr[leftchild]和arr[rightchild]的大小,假設arr[leftchild]更大,將arr[leftchild]再與arr[x]比較,如果arr[leftchild]>arr[x],將arr[leftchild]和arr[x]交換,使以x為根節點的這棵子樹滿足大頂堆的特點。
1.3x - -,重複1.2,直到x==0。
將陣列arr調整成乙個大頂堆後,堆的根節點,即arr[0]是陣列中最大的那個數,將arr[0]與arr[length-1]交換,這時最大的元素就被交換到了陣列尾部。
交換了arr[0]與arr[length-1]後,原本調整好的堆的順序就亂了,所以需要重新調整以arr[0]作為根節點的樹,將其調整成乙個新得大頂堆,不過這時候參與調整的元素不在是0 ~ arr.length-1,而是0 ~ arr.length-2,因為此時陣列尾部已經是最大的那個數了,不需要在參加排序。重新調整成大頂堆後將arr[0]與arr[length-2]交換。交換後原本調整好的堆結構又變化了,這時又重新調整以arr[0]為根節點的樹堆結構,不過參與調整的元素為0 ~ length-3,調整好後又交換arr[0]與arr[length-3]。然後又以arr[0]為根節點調整成大頂堆…這樣不斷調整、交換、調整、交換,直到要參與調整的元素是0~0。
介紹了這些,可能你還沒怎麼理解,建議自己寫幾個數來畫畫圖,結合下面的**,進一步理解堆排序,因為這的確不好說。
**實現
/**
* @author chenzhiyuan
* @date 2019-10-17 23:39
*/public
class
heapsort
for(
int i = nums.length -
1; i >
0; i--)}
/** * 將以nums[root]作為根節點的子樹調整為大頂堆
** @param nums 待排序的陣列
* @param root 表示當前要調整成大頂堆的子樹的根節點的下標,注意不一定是整個nums對應的樹的根,還可能是子樹的根
* @param length 參與調整的元素的個數,也就是思路介紹中第一次是對0~nums.length的元素調整,第二次是以0~nums.length-1的元素調整...
*/private
static
void
adjuctheap
(int
nums,
int root,
int length)
// 比較根節點和和nums[k]的大小
if(nums[k]
> nums[root]
)else}}
public
static
void
swap
(int
nums,
int i,
int j)
}
測試耗時// 建立隨機數
public
static
int[
]createnum
(int size,
long seed)
return nums;
}// 測試5輪
public
static
void
testtime
(int size)
;int
nums =
createnum
(size, seeds[0]
);long start = system.
currenttimemillis()
;heapsort
(nums)
;long end = system.
currenttimemillis()
; system.out.
println
("耗時:"
+(end - start)
+"ms");
nums =
createnum
(size, seeds[1]
);start = system.
currenttimemillis()
;heapsort
(nums)
; end = system.
currenttimemillis()
; system.out.
println
("耗時:"
+(end - start)
+"ms");
nums =
createnum
(size, seeds[2]
);start = system.
currenttimemillis()
;heapsort
(nums)
; end = system.
currenttimemillis()
; system.out.
println
("耗時:"
+(end - start)
+"ms");
nums =
createnum
(size, seeds[3]
);start = system.
currenttimemillis()
;heapsort
(nums)
; end = system.
currenttimemillis()
; system.out.
println
("耗時:"
+(end - start)
+"ms");
nums =
createnum
(size, seeds[4]
);start = system.
currenttimemillis()
;heapsort
(nums)
; end = system.
currenttimemillis()
; system.out.
println
("耗時:"
+(end - start)
+"ms");
}
結果如下:
>二十萬資料
耗時:56ms
耗時:49ms
耗時:38ms
耗時:40ms
耗時:36ms
>一千萬資料
耗時:2037ms
耗時:1747ms
耗時:1937ms
耗時:1705ms
耗時:1703ms
堆排序 堆排序優化 索引堆排序
堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...
堆排序 堆排序優化 索引堆排序
堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...
堆排序 模擬堆排序
838.堆排序 輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 1051 m n 105,1 數列中元素 1091 數列中元素 109 輸入樣例 5 ...