二叉堆是完全二叉樹或者是近似完全二叉樹
二叉堆滿足的二個特性:
1.父節點的鍵值總是大於或等於(小於或等於)任何乙個子節點的鍵值
2.每個節點的左子樹和右子樹都是乙個二叉堆(都是最大堆或者是最小堆)
當父節點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆,總是小於或等於任何乙個子節點的鍵值時為最小堆
堆的儲存:
堆的儲存一般是用陣列來儲存,根據完全二叉樹的儲存結構,乙個節點的父節點為(i-1)/2,乙個節點的左孩子為2*i+1,右孩子為2*i+2
堆的建立插入和刪除:
堆得插入:
每次插入都是將新資料放在陣列的最後,可以發現從這個新資料的父節點到根節點必然為乙個有序的數列。
void minheapaddnumber(int *a,int n,int堆的刪除:nnum)
}
//節點從i開始,節點總數n堆化陣列://刪除的時候每次刪除最上面那乙個節點(根節點)
//然後將最後乙個元素放在根節點上
//然後根節點一次與他的左右節點進行比較,找出乙個最小的,進行交換,
//知道到最後乙個節點或者中間 沒有元素可以交換
void minheapfixdown(int a,int i,int n)
if(a[j]>=temp) break;
//這裡很奇妙,將較小的孩子節點往上移動,
//因為上面是和temp進行的比較,所以a[i]=temp這一步可以省略
//只在最後出現一次
a[i]=a[j];
i=j;
j=2*i+1;
} a[i]=temp;
}void minheapdeletenumber(int *a,int n)
有了堆的插入和刪除函式,在考慮將乙個資料進行堆化操作。
例子:可以看出堆化資料的時候,從最後乙個非葉子節點開始,那也就是2*i+1=n-1(索引),或者2*i+2=n-1,所以可以得到 i=n/2-1;即為最後乙個非葉子結點
可以得到**:
//以上就是堆的基本操作。下面來講堆排序建立最小堆
void makeminheap(int *a,int
n)}
堆排序:
首先可以得到堆建好之後,第0個元素肯定是最小的,取出這個資料在執行下堆的刪除,這樣第0個元素又是最小的,重複上述步驟,知道堆中只剩乙個元素直接取出。
由於堆是用陣列模擬的,故堆化後,第一次將a[0] 與 a[n-1]交換,再對a[0,n-2]進行恢復,重複直到a[0]與a[1]交換,由於每次都是將最小的資料併入到後面的區間,所以操作完成後整個陣列就有序了。所以使用最小堆排序後是遞減陣列,要得到遞增資料,可以使用最大堆
//堆排序的時間複雜度:堆排序void minheapsorttodescendarray(int *a,int
n)}
由於每次重新恢復堆的時間複雜度是o(logn),共n-1次重新恢復堆操作,再加上前面建立堆時n/2次向下調整,每一次時間複雜度也是o(logn);
所以堆排序的時間複雜度是o(nlogn);
二叉堆和堆排序
二叉 堆是乙個陣列,它可以近似看作完全二叉樹。樹上的每乙個節點對應陣列中的乙個元素。除了最底層,該樹是完全充滿的,而且是從左向右填充。根據節點下標可以求出對應的子樹和雙親 parent i return i 2 i表示陣列中的第幾個元素,i 2 表示取整數 left i return 2 i rig...
二叉堆和堆排序的python實現
二叉堆本質上是一種完全二叉數 二叉堆建立 根據原陣列,然後從最後乙個非葉子節點開始,依次下沉,得到最後序列 二叉堆操作 圖比較麻煩就不畫了,可以參考這篇文章 二叉堆 1.二叉堆實現 儲存方式 利用陣列順序儲存 定位方法 利用陣列下標進行定位 父節點parent,左子樹 2 parent 1,右子樹 ...
排序二 堆排序
子結點的鍵值或索引總是小於 或者大於 它的父節點。堆通過一維陣列實現。在起始陣列為 0 的情形中 父節點i的左子節點在位置 2 i 1 父節點i的右子節點在位置 2 i 2 子節點i的父節點在位置 floor i 1 2 堆中的最大值總是位於根節點。堆中定義以下幾種操作 1 最大堆調整 max he...