堆是一種特殊的樹,他有倆個要求
1 堆是乙個完全二叉樹
2 堆每乙個節點的值,都大於等於(或小於等於)其左右子樹節點的值
解釋一下:
第一點,完全二叉樹就是除了最後一層,其它層的節點數都是滿的,最後一層的節點都靠左排列
每個節點都大於等於左右子樹節點的叫做大頂堆,每個節點都小於等於左右子樹節點的叫做小頂堆
12 是大頂堆,3是小頂堆,4不是堆
要實現乙個堆,首先我們需要知道如何儲存乙個堆
我們之前講過,完全二叉樹比較適合陣列來儲存,用陣列去儲存乙個完全二叉樹,非常的節省空間單純的通過下標,就可以找到乙個節點的左右子節點,和父節點
下標為i的節點,左子節點的下標為i2,右子節點的下標i2+1,父節點的下標i/2
向堆中插入乙個資料
每當插入乙個資料,我們還需要繼續滿足堆的倆個特性
如果我們把新插入的資料放到堆的最後,那麼就不滿足堆的倆個特性,那麼就需要調整一下,讓他重新復合這個特性,這個過程我們叫做堆化
堆化有倆種方式,從下向上和從上向下,我們先說從下向上
我們讓新插入的節點,和父節點進行比較,如果不滿足堆的特性,那麼久交換一下,一直重複這個過程,直到滿足為止
刪除堆頂元素從堆的定義來看,堆頂儲存的是堆中最大元素或者最小元素,假如我們刪除的是大頂堆,堆頂是最大元素,那該如何正確的刪除呢?
我們可以把最後乙個元素放到堆頂,然後從堆頂開始,對比父子節點的資料,不滿足要求的交換,一直重複,直到滿足父子節點的關係為止,這個就是從上向下的堆化
}乙個完全二叉樹,高度不大於log2n,而堆化是根據節點的所在路徑進行交換的,所以跟樹的蓋度成正比時間複雜度為o(logn),插入和刪除主要邏輯就是堆化,說以時間複雜度為o(logn)
我們可以把堆排序分為倆個操作,建堆和排序
建堆
建堆指的是,把乙個無需陣列建成乙個符合堆定義的陣列,建堆有倆種思路,一種就是上面的插入,我們可以假設堆中只有乙個元素,然後把2到n的元素依次插入,這樣就組成了堆
第二種思路和第一種相反,第一種是從前向後處理資料,從下向上堆化,第二種是從陣列後向前處理資料,從上向下堆化
因為葉子節點向下堆化只能和自己比較,所以我們需要從第乙個非葉子節點的開始堆化
}第乙個非葉子節點是從 n/2 開始的,n/2+1 到 n 都是葉子節點我們不需要堆化,建堆的時間複雜度為o(n)
排序
經過建堆以後,現在已經是大頂堆了,堆頂就是最大元素,我們把堆頂移到下標n的位置,然後剩下的進行堆化,然後重複上方的操作,和刪除堆頂元素差不多,直到堆中只有乙個元素,就排序完成了
堆排序的完整**
// n 表示資料的個數,陣列 a 中的資料從下標 1 到 n 的位置。
public static void sort(int a, int n)
}
整個堆排序後只需要極少的臨時空間,所以堆排序是原地排序建堆時間複雜度o(n),排序是將複雜度為o(nlogn),所以堆排序的時間複雜度為o(nlogn)堆排序不是穩定排序,因為在堆排序過程中,存在把最後乙個元素和第乙個元素交換的過程,會打亂原有的順序
上面所有的操作都是假設陣列是從下標1出開始的,如果下標是從0開始的,處理的思路是沒有任何改變的,唯一的變化就是計算子樹座標的公式
如果下標從0開始,那麼節點的下標是i,左子節點下標就是2i+1,右子節點就是2i+2,父節點就是i-1/2。
所有的**
/**
* 大頂堆
*/public class head
//堆中插入資料
public void insert(int data)
}//堆中刪除堆頂元素
public void removemax()
private void heapify(int a, int n, int i)
}//堆排序 假設陣列是從下標1開始的
public void sort(int a, int n)
}//建堆
private void buildheap(int a, int n) }}
資料結構和演算法之路 堆和堆排序
1.是一種完全二叉樹,第n層至少有 2 n 1 個結點 2.大頂堆 父節點 大於左右子結點 小頂堆 父節點小於左右子結點 3.用一維陣列來表示 4.最後乙個非葉結點的下標 length 2 1 parent floor i 1 2 i 1 left i 2 1 right i 2 2 1.shift...
資料結構 堆(堆排序和模擬堆)
輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 10 5,1 數列中元素 10 9 輸入樣例 5 34 5 1 3 2 輸出樣例 1 2 3 演算法的...
資料結構 排序演算法 選擇排序和堆排序
選擇排序 1.基本思想 以公升序為例,假設有n個資料,每一趟在後面n i的待排序的資料元素集合中選出關鍵碼最小的資料元素,作為有序序列的第i個元素,直至待排序集合中只剩下1個元素。2.操作步驟 舉乙個例子 3.演算法效能 時間複雜度 直接選擇演算法需要遍歷每一趟選出最小的乙個數,遍歷n遍,時間複雜度...