排序之堆排序
堆排序時間復(fù)雜度:O(NlogN).二叉堆:是完全二叉樹。將其結(jié)點存入數(shù)組的話,任意一非葉結(jié)點位置存在以下的兩種關(guān)系
1、k[i]<=k[2*i+1] && k[i]<=k[2*i+2] (小頂堆) 小頂堆堆頂關(guān)鍵字肯定是所有關(guān)鍵字中最小的
2、k[i]>=k[2*i+1] && k[i]>=k[2*i+2] (大頂堆) 大頂堆堆頂關(guān)鍵字肯定是所有關(guān)鍵字中最大的
堆排序的思想:
1、將初始待排序關(guān)鍵字序列(x1,x2,x3,...,Xn)構(gòu)成大頂堆,此堆為初始的無序區(qū);
2、將堆頂元素x1與最后一個元素xn交換,此時得到新的無序區(qū)(x1,x2,x3,..,Xn-1)和新的有序區(qū)(Xn) 且 Xn最大
3、由于交換后新的堆頂元素可能違反堆的性質(zhì),因此需要對當(dāng)前無序區(qū)重新調(diào)整為堆,然后依次再將x1與Xn-1交換,如此重復(fù)直到有序區(qū)的個數(shù)為n-1。
1 ?#include<iostream>
?2 ?#include<algorithm>
?3 ?using namespace std;
?4 ?//調(diào)整堆 a[]={16,7,3,20,17,8}
?5 ?//上溯算法,將新的結(jié)點與父結(jié)點比較,如果其鍵值大于父結(jié)點,交換位置。如此一直上溯,直到不需要對換或到根結(jié)點為止
?6 ?void HeapAdjust(int *a,int i,int size)
?7 ?{
?8 ???????? int lchild=2*i+1;
?9 ???????? int rchild=2*i+2;
10 ???????? int max=i;
11 ???????? if(lchild<=size-1&&a[lchild]>a[max])
12 ???????? max=lchild;
13 ???????? if(rchild<=size-1&&a[rchild]>a[max])
14 ???????? max=rchild;
15 ???????? If(max!=i)
16 ??{
17 ??swap(a[i],a[max]);
18 ??HeapAdjust(a,max,size); //避免調(diào)整之后以max為父節(jié)點的子樹不是堆
19 ??}
20
21 ?}
22 ?//建立堆
23 ?void BuildHeap(int *a,int size)
24 ?{
25
26 ???????? int i;
27????????? for(i=size/2-1;i>=0;i--)
28 ?{
29 ? HeapAdjust(a,i,size);
30
31 ?}
32
33 ?}
34
35
36 ? void HeapSort(int *a,int size)
37 ? {
38?? ????? int i;
39 ???????? BuildHeap(a,size);
40?? for(i=size-1;i>=0;i--)
41 ?{
42 ???????? swap(a[0],a[i]);
43 ???????? HeapAdjust(a,0,i);
44 ?}
45 ?}
? 堆排序是不穩(wěn)定的排序算法,穩(wěn)定的排序算法通俗地講就是能保證排序前2個相等的數(shù)其在序列的前后位置順序和排序后它們兩個的前后位置順序相同。在簡單形式化一下,如果Ai = Aj,Ai原來在位置前,排序后Ai還是要在Aj位置前,平均時間復(fù)雜度和最差時間復(fù)雜度都是O(NlogN),空間復(fù)雜度為O(1)
轉(zhuǎn)載于:https://www.cnblogs.com/wsw-seu/p/7654753.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: 清北学堂模拟赛d3t2 b
- 下一篇: poj1789 Truck Histor