認識堆以前,首先要明確兩個概念:滿二叉樹和完全二叉樹:
滿二叉樹:在一棵二叉樹中,如果所有分支節點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱為滿二叉樹。
完全二叉樹:對一棵具有 n 個節點的二叉樹按層序編號,如果編號為 i 的節點與同樣深度的滿二叉樹中編號為 i 的節點在二叉樹中的位置完全相同,則這棵二叉樹稱為完全二叉樹。
堆:堆是具有下列性質的完全二叉樹:每個結點的值都大於或等於其左右孩子節點的值,稱為大頂堆;或者每個節點的值都小於或等於其左右孩子節點的值,稱為小頂堆。
該方法的思路是把陣列先全部載入到陣列裡,然後按照完全二叉樹的結構從下往上,從右往左逐步建堆,最後把整個二叉樹擴充套件成堆。
時間複雜度分析:
設有 n 個節點,則這 n 個節點構成的完全二叉樹深度為 log(n),把高度設為 h
第 m 層最多的節點個數是 2^(m) ,每個節點需要下移的最多的次數是 (h - m) 次,則時間複雜度
t = 2^(h - 1) * 1 + 2^(h - 2) * 2 + 2^(h - 3) * 3 + … + 2^1 * (h - 1) + 2^0 * (h) (1)
等式兩邊同乘 2
2t=2^h * 1 + 2^(h - 1) * 2 + 2^(h - 2) * 3 + 2^(h - 3) * 4 + …+2^1 * (h) (2)
用 (2) 式減 (1) 式得
t = 2^h + 2^(h - 1) + 2^(h - 2) + … + 2^1 - 2^0 (3)
根據等比數列求和公式得
t = 2^(h + 1) - h - 1
h = log2(n),所以得 t = n - log2(n) + 1,即時間複雜度為 o(n)
**:
void
createheap()
;int currentpos =
(arr.length -2)
/2;//最後乙個非葉子節點
while
(currentpos >=0)
}//構建大根堆
void
filterdown
(int
arr,
int start,
int end)
if(temp < arr[j]
)else
} arr[i]
= temp;
}
該方法的思路是每次把資料插入到堆的最後乙個位置,逐步把該節點往上公升,直到公升不動為止。
時間複雜度:這種方法的時間複雜度很好分析,一共 n 個節點,每個節點最大比較 log2(n) 次,所以時間複雜度就是 n * log2(n)
void
createheap()
;//相當於是乙個乙個插入到堆的末尾,再向上調整成堆
int currentpos =0;
while
(currentpos < arr.length)
for(
int i : arr)
}void
filterup
(int
arr,
int end)
else
break;}
else
break;}
arr[i]
= temp;
//移動到最後的位置,這種方式減少了交換次數
}
第一種建堆方式主要用於堆元素已經確定好的情況,第二種方式主要用於動態增加元素來建堆。插入建堆的過程也常用於建立優先佇列的應用。
堆排序的基本思想就是把待排序的序列造成乙個大頂堆。此時,整個序列最大的值就是堆頂的根節點。將它移走(為了節省空間,就直接和最後乙個節點互換位置了),然後將剩餘 n - 1 個節點重新構造成乙個堆,這樣就會得到 n 個元素中的次小值。如此反覆執行,便能得到乙個有序序列了(如果用了節省空間的方法,那麼大根堆得到的是公升序序列,小根堆得到的是降序序列)。
時間複雜度:
共需要移走 n 個節點,每移走乙個節點重新建堆需要 log(n) 的時間,所以時間複雜度為 n * log(n)
空間複雜度:
沒有開闢額外的空間,所以是 o(1),如果不用節省空間的方法,空間複雜度是 o(n)。
因為堆排序存在跳躍,所以堆排序是不穩定的(隨手畫一下就發現了)。
void
createheap()
;int currentpos =
(arr.length -2)
/2;//最後乙個非葉子節點
while
(currentpos >=0)
}//構建大根堆
void
filterdown
(int
arr,
int start,
int end)
if(temp < arr[j]
)else
} arr[i]
= temp;
}//只在建好的堆上加個排序方法即可
void
sort
(int
arr)
}
堆和堆排序
堆是一種靈巧的 部分有序的資料結構,它尤其適合用來實現優先佇列。優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱為元素優先順序的可排序屬性。優先佇列支援下面的操作 通過採用堆這種資料結構可以高效實現這些操作。下文分兩部分 第一部分介紹堆 第二部分講解堆排序。堆可以定義為一棵二叉樹,樹的節點中包含...
堆和堆排序
這個題大意是有乙個資料結構支援兩種操作a與 get操作,其中 a x表示插入 x.get i 表示返回結構中的第 i小的數.給你 a和get操作的順序和引數 現在要你對每個 get輸出值 題解 每次取第k小元素,k不斷更新。使用兩個堆,來完成。小頂堆負責選出最小的元素,大頂堆負責選出k個元素中最大的...
堆和堆排序
堆排序演算法 優先佇列 堆的性質的維護,以下都以最大堆為例。堆的維護的主要思想是 逐層下降 舉例 某個結點i,假設其左右子結點left i right i 都已經是最大堆,那麼需要調節 或者說是調換 i,left i right i 的值,並保證調換後的子樹繼續調換下去直到子樹繼續滿足堆的性質。首先...