排序算法——堆排序
堆排序
1.基礎概念
-
二叉樹的概念:
二叉樹(binary tree)是指樹中節點的 度 不大于2的有序樹. 在二叉樹中除了根節點的每一個節點都僅有一個父節點,所有的節點最多只能有兩個
孩子節點。 -
滿二叉樹的概念:
除最后一層無任何子節點外,每一層上的所有結點都有兩個子結點的二叉樹。
國內教材定義:
一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹。也就是說,如果一個二叉樹的層數為K,且結點總數是(2^k) -1 ,則它就是滿二叉樹。
國外(國際)定義:
a binary tree T is full if each node is either a leaf or possesses exactly two childnodes.
-
完全二叉樹:
對滿二叉樹的結點進行編號, 約定編號從根結點起, 自上而下, 自左而右。則深度為k的, 有n個結點的二叉樹, 當且僅當其每一個結點都與深度為k的滿二叉樹中編號從1至n的結點一一對應時 。
-
堆的概念:
堆通常是一個可以被看做一棵完全二叉樹。
- 二叉樹的存儲方式
(1) 按照完全二叉樹(無論是那種二叉樹)的形式,將二叉樹的數據全部存儲在數組中.
(2) 順序表中的每個元素除了存儲data,leftchild , rightchild
- 堆僅僅將數據存儲在數組中
2.堆的建立過程
- 將數組中的數據調整成堆時,從最后一棵子樹開始,向根節點一顆顆調整
每棵子樹的調整都是從其根節點開始向下調整的 - 一棵子樹的調整過程:
先用i指向子樹的根節點,j為根節點的左孩子。將i位置的值保存到tmp中, 然后在左右孩子中找到較大的哪一個,j指向較大值,(1)如果較大的哪一個比臨時變量中的值小,則直接退出;(2)如果較大的哪一個比臨時變量中的值大,則將較大的值保存到i位置上,然后i=j,j=2*i+1,直到j越界則退出。退出以后,還需要將tmp的值保存到退出時的i位置上。
代碼實現
void OneAdjust(int *arr, int len, int root) {int tmp = arr[root];int i = root;int j = 2 * i + 1;while (j < len){// j+1 < len 成立 則有右孩子// arr[j] < arr[j+1] 左孩子的值小于右孩子if (j + 1 < len && arr[j] < arr[j + 1]) j++;if (arr[j] < tmp) break;arr[i] = arr[j];i = j;j = 2 * i + 1;}arr[i] = tmp; }- 將數組調整成堆的過程
先找到最后一棵子樹的根節點,向根節點遞減,循環調用上面的調整方法。
代碼實現
void CreateHeap(int *arr, int len) {int lastRoot = (len - 2) / 2; // lastRoot就是最后一棵子樹的根節點下標for (int i = lastRoot; i >= 0; --i) // 從lastRoot開始,循環到整顆數的根節點,調整{OneAdjust(arr, len, i);} }3.堆排序
- 先將數組中的數據調整成一棵最大堆, 然后將根節點的數據和最后位置的節點交換, 接著除過最后一個位置的數據外,在將剩余的數據調整成
最大堆。 - 重復上述過程,直到只剩下一個數據沒有交換。就完成了堆排序。
總結
- 上一篇: 排序算法——直接插入排序
- 下一篇: 排序算法——归并排序