算法day03

80 阅读1分钟

1.堆排序

public void heapify(int[] nums,int index,int size){
    int left = index*2+1;
    int right = index*2+2;
    while(left<size){
        //返回孩子中的最大值的下标
        int largest = right<size && nums[right]>nums[left]? right:left;
        largest = Math.max(nums[largest],nums[index])==nums[largest]? largest:index;//取当前节点和其所有孩子节点中较大的一个,返回下标largest
        if(largest==index) break;//如果当前元素比孩子节点大,说明已经是大根堆
        exchange(nums,largest,index);//如果不是,交换元素值
        index = largest;
        left = index*2+1;
    }
}

public void heapInsert(int[] nums,int index){
    while (nums[index]>nums[(index-1)/2]){
        exchange(nums,index,(index-1)/2);
        index = (index-1)/2;
    }
}

public void heapSort(int[] nums){
    if(nums.length==0||nums==null) return;
    int heapSize = 0;
    //将数组整体构建成一个大根堆
    while (heapSize<nums.length){
        heapInsert(nums,heapSize);
        heapSize++;
    }
    exchange(nums,0,heapSize-1);  //交换首位和末尾
    heapSize--;                     //最大值在末尾,这个数找到了最终位置

    // 每次构建一个大根堆,交换0位置和heapSize-1位置再次排成大根堆
   while (heapSize>0){
       heapify(nums,0,heapSize);
       exchange(nums,0,heapSize-1);
       heapSize--;
    }
}
  1. 堆排序拓展

    一个基本有序的数组,指的是每个元素排序过后的位置与原始位置相差不超过k,选择合适的方法对其进行排序。用堆排序时间复杂度为O(NlogK),当K的值相对N来说很小的话,logK几乎可以忽略,整个算法接近O(N)的时间复杂度,比较高效。*

public void sortArrDistanceLessK(int[] nums,int k){
    PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
    int index = 0;
    for (; index < k; index++) {
        priorityQueue.add(nums[index]);
    }
    int i = 0;
    for (; index < nums.length; i++,index++) {
        nums[i] = priorityQueue.poll();
    }
    while(!priorityQueue.isEmpty()){
        nums[i++] = priorityQueue.poll();
    }
}

3.基数排序


public void radixSort(int[] nums){
    if(nums==null||nums.length<2) return;
    int maxbits = maxbits(nums);//数组中最大值有多少位
    int[] help = new int[nums.length];//出桶辅助数组
    for (int i = 1; i <= maxbits; i++) {//共进行maxbits轮入桶出桶操作
        int[] count = new int[10];//某位记录<=i的数字有多少个
        for (int j = 0; j < nums.length; j++) {//更新count数组
            int bitNum = getbitNum(nums[j], i);
            count[bitNum]++;
        }
        //将count数组转为前缀和数组,表示当前某位<=i的数字有多少个
        for (int m = 1; m < count.length; m++) {
            count[m] = count[m-1]+count[m];
        }
        for (int m = nums.length-1; m >=0; m--) {
            int bitNum = getbitNum(nums[m], i);//当前元素该位数字
            help[count[bitNum]-1] = nums[m];
            count[bitNum]--;
        }//出桶完成
       //写入原数组
        for (int m = 0; m < nums.length; m++) {
            nums[m] = help[m];
        }
    }
}
//  求当前数组中最大值最多有多少位
public int maxbits(int[] nums){
    int max = nums[0];
    for (int i = 1; i < nums.length; i++) {
        max = Math.max(nums[i],max );
    }
    int res = 0;
    while(max!=0){
        max/=10;
        res++;
    }
    return res;
}

//求当前数字的个位/十位/百位.....
public int getbitNum(int num,int bit){
    num = (num/((int) (Math.pow(10,bit-1)))%10);
    return num;
}