實現最大堆(包括插入和從堆中取出元素)及第一種堆排序【Java版】
阿新 • • 發佈:2019-02-13
/**
*實現最大堆
*用陣列儲存
*小優化:將swap用賦值代替,先不急著交換,先複製,再移動,最後賦值
*第一種堆排序,從小到大排序
*時間複雜度為O(nlogn)
*空間複雜度O(n)
*/
public class MaxHeap {
private int count; //記錄堆中儲存元素的個數
private static int[] data; //用陣列儲存二叉堆
private int capacity;
public MaxHeap(int capacity) {
//在構造方法中初始化
count=0 ;
data=new int[capacity+1];//因為根節點從1開始,所以儲存空間加1
//不能省略,否則預設類中的capacity為0;
this.capacity=capacity;
}
//判斷堆是否為空
boolean isEmpty() {
return count==0;
}
//輸出堆中元素個數
int size() {
return count;
}
public int getCapacity() {
return this.capacity;
}
//向堆中新增元素
public void insert(int item ) {
//先將新增的元素加到最後一個元素後面
//有索引還得考慮索引越界問題,最好的解決方案是動態擴充套件堆
//這樣可以不受堆容量限制,容量不足開闢新空間
if(count++<=getCapacity()) {
//count指向所新增的元素
data[count]=item;
//再將item向上移動,與父節點比較,如果比父節點大,則交換
shiftUp(count);
}
}
//向上移動,將item與父節點比較,如果比父節點大,則交換
private void shiftUp(int i) {
while(i>1&&data[i]>data[i/2]) {
swap(i,i/2);
i/=2;
}
}
//從堆中取出元素,優先佇列思想
public int extractMax() {
if(count<=0)
return 0;
//先取出最大的(優先順序高的)
int max=data[1];
//將堆中最後一個元素存入第一元素的位置
swap(1, count);
count--;
//將第一個元素向下移,找到合適位置,維護堆
shiftDown(1);
return max;
}
private void shiftDown(int i) {
//定義左孩子,完全二叉樹如果有孩子,一定有左孩子
while (2*i<=count) {
int j=2*i;
//j+1即為右孩子
if(j+1<=count&&data[j+1]>data[j])
j+=1;
if(data[i]>=data[j])
break;
swap(i, j);
i=j;
}
}
private void swap(int i, int j) {
if(i!=j) {
int temp=data[i];
data[i]=data[j];
data[j]=temp;
}
}
public void print(int []data,int count) {
for(int i=0;i<=count;i++)
System.out.print(data[i]+" ");
System.out.println();
}
//測試這裡寫程式碼片
public static void main(String args[]) {
//建立堆
MaxHeap maxHeap =new MaxHeap(100);
//向堆中存,插入元素,入隊
for(int i=0;i<20;i++) {
maxHeap.insert((int)(Math.random()*100));
}
maxHeap.print(data,maxHeap.count);
System.out.println(maxHeap.size());
//從堆裡取,依次取出最大值,從大到小
while(!maxHeap.isEmpty()) {
System.out.print(maxHeap.extractMax()+" ");
}
}
}
/**
*實現堆排序
*時間複雜度為O(nlogn)
*空間複雜度O(n)
*根節點從1開始,左孩子:2i,右孩子2i+1;
*/
public class HeapSort1 {
public void heapSort1(int[]arr,int n) {
MaxHeap heap1=new MaxHeap(n);
//存入堆
//這一步可以優化,不用每一個元素都要insert一次
for(int i=0;i<n;i++) {
heap1.insert(arr[i]);
}
//從小到大排序
for(int i=n-1;i>=0;i--) {
arr[i]=heap1.extractMax();
}
}
public static void main(String[] args) {
int [] arr= {8,7,4,5,9,2,10,3,3,3,30,3};
int n=arr.length;
HeapSort1 sort1=new HeapSort1();
sort1.heapSort1(arr, n);
for(int i=0;i<n;i++)
System.out.print(arr[i]+" ");
}
}