堆排序

百度解释:堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

大顶堆

public class HeapSort {
    public static void adjustMaxHeap(int[] array,int lastindex){
        for (int i = (lastindex-1)/2; i>=0 ; i--) {
            int k=i;
            while(k*2+1<=lastindex){
                int biggerindex=k*2+1;
                if(biggerindex<lastindex){//防止溢出
                    if(array[biggerindex]<array[biggerindex+1]){
                        biggerindex++;
                    }
                }
                if(array[k]<array[biggerindex]){
                    swap(array,k,biggerindex);
                    k=biggerindex;
                }else{
                    break;
                }
            }
        }
    }

    public static void heapSort(int[] array){
        for (int i = 0; i <array.length-1 ; i++) {
            adjustMaxHeap(array,array.length-1-i);
            swap(array,0,array.length-1-i);
        }
    }

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

    public static void main(String[] args) {
        int[] array={1,7,8,9,6};
        heapSort(array);
        for(int a:array){
            System.out.println(a);
        }
    }
}

小顶堆

public class HeapSort2 {

    public static void adjustMinHeap(int[] array,int lastindex){
        //i初始值为最后一个非子节点的索引
        for (int i = (lastindex-1)/2; i>=0 ; i--) {
            int k=i;
            while(2*k+1<=lastindex){
                int smallerindex=k*2+1;
                if(smallerindex<lastindex){
                    if(array[smallerindex]>array[smallerindex+1]){//左孩子值大于有孩子则交换
                        smallerindex++;
                    }
                }
                if(array[k]>array[smallerindex]){//最小子节点的值小于父节点的值则交换
                    swap(array,k,smallerindex);
                    k=smallerindex;
                }else{
                    break;
                }
            }
        }
    }

    public static void heapSort(int[] array){
        for (int i = 0; i <array.length ; i++) {
            adjustMinHeap(array,array.length-1-i);
            swap(array,0,array.length-1-i);
        }
    }

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

    public static void main(String[] args) {
        int[] array={1,7,8,9,6};
        heapSort(array);
        for(int a:array){
            System.out.println(a);
        }
    }
}

双堆求中位数:

算法描述:

1、创建两个堆(一个小顶堆、一个大顶堆),堆大小至少为给定数据个数的一半,向上取整;

2、假定变量mid用来保存中位数,取定第一个元素,赋值给mid,即作为初始的中位数;

3、依次遍历后面的每一个数据,如果比mid小,则插入大顶堆;否则插入小顶堆;

4、如果大顶堆和小顶堆上的数据个数相差为2,则将mid插入到元素个数较少的堆中,然后从元素个数较多的堆中删除根节点,并将跟节点赋值给mid;

5、重复步骤3和4,直到所有的数据遍历结束;

此时,mid保存了一个数,再加上两个堆中保存的数,就构成了给定数据的集合。

如果两个堆中元素个数相等,则mid即为最终的中位数;否则,元素较多的堆的根节点元素与mid的和求平均值,即为最终的中位数。

public class HeapSort3 {

    public static void adjustMaxHeap(List<Integer> list,int lastindex){
        for (int i = (lastindex-1)/2; i>=0 ; i--) {
            int k=i;
            while(k*2+1<=lastindex){
                int biggerindex=k*2+1;
                if(biggerindex<lastindex){//防止溢出
                    if(list.get(biggerindex)<list.get(biggerindex+1)){
                        biggerindex++;
                    }
                }
                if(list.get(k)<list.get(biggerindex)){
                    swap(list,k,biggerindex);
                    k=biggerindex;
                }else{
                    break;
                }
            }
        }
    }

    public static void adjustMinHeap(List<Integer> list,int lastindex){
        //i初始值为最后一个非子节点的索引
        for (int i = (lastindex-1)/2; i>=0 ; i--) {
            int k=i;
            while(2*k+1<=lastindex){
                int smallerindex=k*2+1;
                if(smallerindex<lastindex){//防止越界
                    if(list.get(smallerindex)>list.get(smallerindex+1)){//左孩子值大于有孩子则交换
                        smallerindex++;
                    }
                }
                if(list.get(k)>list.get(smallerindex)){
                    swap(list,k,smallerindex);
                    k=smallerindex;
                }else{
                    break;
                }
            }
        }
    }


    public static void swap(List<Integer> list,int i,int j){
        int temp=list.get(i);
        list.set(i,list.get(j));
        list.set(j,temp);
    }

    private static void getMiddle(List<Integer> list) {
        if(list.size()==1){
            System.out.println("中位数为:"+list.get(0));
            return;
        }
        List<Integer> maxlist=new ArrayList<Integer>();//左堆-->大顶堆
        List<Integer> minlist=new ArrayList<Integer>();//右堆-->小顶堆
        int maxlen=0;//大顶堆内结点个数
        int minlen=0;//小顶堆内结点个数
        int mid=list.get(0);//中位数
        for (int i = 1; i <list.size() ; i++) {
            if(mid>list.get(i)){
                maxlist.add(list.get(i));
                maxlen++;
                adjustMaxHeap(maxlist,maxlen-1);
            }else{
                minlist.add(list.get(i));
                minlen++;
                adjustMinHeap(minlist,minlen-1);
            }
            if(minlen-maxlen>1){
                //maxlist.add(mid);
                //adjustMaxHeap(maxlist,maxlen);
                maxlist.add(0,mid);
                mid=minlist.get(0);
                minlist.remove(0);
                maxlen++;
                minlen--;
            }
            if(maxlen-minlen>1){
//                minlist.add(mid);
//                adjustMinHeap(minlist,minlen);
                minlist.add(0,mid);
                mid=maxlist.get(0);
                maxlist.remove(0);
                maxlen--;
                minlen++;
            }
        }
        if(minlen>maxlen){
            mid=(mid+minlist.get(0))/2;
        }else if(minlen<maxlen){
            mid=(mid+maxlist.get(0))/2;
        }
        System.out.println("中位数为:"+mid);
    }

    public static void main(String[] args) {
        List<Integer> list=new ArrayList<Integer>();
        list.add(2);
        list.add(20);
        list.add(13);
        list.add(18);
        list.add(15);
        list.add(8);
        list.add(3);
        list.add(5);
        list.add(4);
        list.add(25);
        getMiddle(list);
    }
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值