栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

B站左程云算法视频03

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

B站左程云算法视频03

堆是一个完全二叉树结构(包括满二叉树和从左到右变满的二叉树)

二叉树中,对于i节点,左子孩子为2*i+1,右子孩子为2*i+2 父节点为(i-1)/2     用于后续的找

大根堆:完全二叉树里,每一棵子树的最大值是头结点的值

小根堆:每一棵子树的最小值是头结点的值

heapInsert

public static void heapInsert(int[] arr, int index) {
    while(arr[index] > arr[(index-1)/2]) {//与父节点比较,0位置也不成立
        swap(arr, index, (index-1)/2);
        index = (index-1)/2;
    }

}

给定一组数,找出最大值,大根堆的0位置的数;去掉最大值,先设定一个临时变量存最大值,然后把以及形成的堆结构的最后一个位置的数放到0位置上,heapsize-1,然后从头结点开始,与其子节点的最大值进行比较交换,若还有孩子,则继续比较,直到无孩子或不大于则停止

heapify
//某个数在index位置,能否向下移动
public static void heapify(int[] arr, int index, int heapSize){
    int left = index * 2 + 1;//左孩子的下标
    while(left < heapSize){//下方还有孩子时
     //两个孩子中,谁的值大,把下表给largest
        int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
     //父和孩子之间,谁的值大,把下标给largest
        largest = arr[largest] > arr[index] ? largest : index;
        if(largest == index){
            break;
        }
        swap(arr, largest, index);
        index = largest;
        left = index * 2 + 1;
    } 
}

给定一个堆,修改i位置数,如果i位置数变大,则往上heapInsert ,变小,往下heapify

完全二叉树的高度

heapInsert和heapify 级别的调整代价

堆排序heapSort

代码:

public static void heapSort(int[] arr){
    if(arr == null || arr.length < 2){
        return ;
    }
    for (int i = 0; i< arr.length; i++){
        heapInsert(arr,i);
    
    }
    int heapSize = arr.length;
    swap(arr, 0 --heapSize);
    while(heapSize > 0){
        heapify(arr, o ,heapSize);
        swap(arr, o ,--heapSize);
    }//把最大值放在刚失效的位置
}

堆排序的时间复杂度 空间复杂度O(1)

问题:给一组数,怎么变成大根堆

public static void heapSort(int[] arr){
    if(arr == null || arr.length < 2){
        return ;
    }
   
    for(int i = arr.length - 1; i>= 0; i--){
        heapify(arr, i ,arr.length);
    }

    int heapSize = arr.length;
    swap(arr, 0 --heapSize);
    while(heapSize > 0){
        heapify(arr, o ,heapSize);
        swap(arr, o ,--heapSize);
    }//把最大值放在刚失效的位置
}

 堆排序扩展题目

堆结构的扩容也是logN级别的,不会影响性能。

Java中现存的堆排序是一个黑盒,不支持已形成的堆结构修改其中一个数,再以小代价形成对结构,所以有时候要自己手写堆结构。

比较器的使用

返回负数的时候,第一个参数放前面;正数的时候,第二个在前面;0无所谓

1)实质上是重载比较运算符

2)比较器可以很好的应用在特殊标准的排序上

3)可以很好的应用在根据特殊标准排序的结构上

比较器可以使用在堆结构里,实现复杂数据的排序。

不基于比较的排序 计数排序

 

基数排序

 

//only for no-negative value
public static void radixSort(int[] arr){
    if (arr == null || arr.length < 2){
        return;
    }
    radixSort(arr, 0, arr.length - 1, maxbits(arr));
}

public static int maxbits(int[] arr){
        int max = Integer.MIN_VALUE;
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
    }
        int res = 0;
        while(max != 0){
            res++;
            max /= 10;
    }    
    return res;
}

//arr[begin..end]排序
public static void radixSort(int[] arr, int L, int R, int digit){//digit最大值有几个十进制位
        final int radix = 10;
        int i = 0, j = 0;
        //有多少个数准备多少个辅助空间
        int[] bucket = new int[R - L + 1];
        for(int d = 1; a <= digit; d++){//有多少位就进出几次
        //10个空间
        //count[0]当前位(d位)是0的数字有多少个
        //count[1]当前位(d位)是0和1的数字有多少个
        //count[2]当前位(d位)是0、1和2的数字有多少个
        //count[i]当前位(d位)是(0~i)的数字有多少个
        int[] count = new int[radix]; // count[0..9]
        for (i = L; i <= R; i++){
            j=getDigit(arr[i], d);
            count[j]++;
}
        for(i = 1; i < radix; i++){
            count[i] = count[i] + count[i-1];
}
        for(i = R; i >= L; i--){        //倒着看数字放
            j = getDigit(arr[i],d);
            bucket[count[j]-1]=arr[i];
            count[j]--;
}
        for(i = L, j = 0; i <= R; i++, j--){
            arr[i] = bucket[j];
}
}
}

public static int getDigit(int x, int d){
    return (( x / (( int) Math.pow(10, d-1))) % 10);
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/881186.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号