堆排序/手写堆

堆排序:
1,开始建堆,已一个小根堆为例:(图片摘自别人,与下面的排序代码无关)


建堆

构造好了堆之后,下面就是排序的过程:


排序


直接上代码了:

public class HeapSort {

    public void sift(int[] arr, int index, int length){
        int temp = arr[index];//先取出当前元素i
        for(int k=index*2+1; k<length; k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
            if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
                k++;
            }
            if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                arr[index] = arr[k];
                index = k;
            }else{
                break;
            }
        }
        arr[index] = temp;//将temp值放到最终的位置
    }

    public void sort(int[] arr){
        for(int i=arr.length/2-1;i>=0;i--){
            //从第一个非叶子结点从下至上,从右至左调整结构
            sift(arr,i,arr.length);
        }
        //2.调整堆结构+交换堆顶元素与末尾元素
        for(int j=arr.length-1;j>0;j--){
            swap(arr,0,j);//将堆顶元素与末尾元素进行交换
            sift(arr,0,j);//重新对堆进行调整
        }

    }

    public void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        int[] arr = {1,43,6,4,3,2,5};
        new HeapSort().sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}


由于是从第二个元素开始排序的也就是a[1],所以第一个元素没有排序,可以在初始化的时候声明为0。


2017/8/7/13:32

今天在算法导论上看到一种用递归实现的方法,只需要把上面的sift方法换一下即可:

void sift2(int a[],int m,int n)
{
    int i = m,j = 2*m,k=2*m+1;
    int largest;
    if(largest > n)return;

    if(a[i]>a[j])largest = i;
    else j = largest;

    if(a[k]>a[largest]) largest = k;

    if(i!= largest)
    {
        swaps(&a[i],&a[largest]);
        sift2(a,largest,n);
    }

}

2020.12.2,时隔三年,再对堆进行一遍温习,以大根堆为例:

手写最大堆代码如下:

import java.util.Arrays;

public class MaxHeap {
    private int[] data;
    private int size;
    private int capacity;

    public MaxHeap(int msize){
        this.size = 0;
        this.capacity = msize;
        data = new int[msize+1];
    }

    public void insert(int v){
        if(size == capacity) {
            System.out.println("heap is full");
            return;
        }
        data[++size] = v;
        shiftup(size);
    }

    private void shiftup(int index) {
        while(index > 1 && data[index] > data[index/2]){
            int t = data[index];
            data[index] = data[index/2];
            data[index/2] = t;
            index /= 2;
        }
    }

    public int deleteMax(){
        if(size == 0) {
            System.out.println("堆已经是空的");
            return -1;
        }
        int res = data[1];
        data[1] = data[size--];
        shiftdown(1);
        return res;
    }

    private void shiftdown(int i) {
        while(2 * i <= size){
            int j = (i << 1);
            if(j + 1 <= size && data[j] < data[j+1]) j++;
            if(data[i] > data[j]) break;
            int t = data[i];
            data[i] = data[j];
            data[j] = t;
            i = j;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,7,10,45,13,3};
        MaxHeap heap = new MaxHeap(arr.length);
        for(int v: arr) {
            heap.insert(v);
        }
        for(int i = arr.length-1; i >= 0; i--){
            arr[i] = heap.deleteMax();
        }
        System.out.println(Arrays.toString(arr));
    }

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值