java数组排序算法02-快速排序,归并排序,基数排序,堆排序

java数组排序算法

快速排序

分治法:比大小,再分区

  1. 从数组中取出一个数,作为基准数
  2. 分区:将比这个数大或等于的数全放到他的右边,小于他的数全放到他的左边
  3. 再对左右区间重复第二步,直到各区间只有一个数
package com.array.arraysort;

import java.util.Arrays;

// 分治法:比大小,再分区
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {2,1,34,5,7,56,3,23};
        // 调用工具类,进行快排 传入数组,起始位置,结束位置
        quick(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quick(int[] arr, int start, int end) {
        // 找出分左右两区的索引位置,然后对左右两区进行递归调用
        if (start<end){
            int index = getIndex(arr,start,end);
            quick(arr,start,index-1);
            quick(arr,index+1,end);
        }

    }

    private static int getIndex(int[] arr,int start,int end){
        int i = start;
        int j = end;
        int x = arr[i]; //基本数
        while(i<j){
            // 由后往前找比他小的数,将此数填到前一个坑中
            while(i<j&&arr[j]>=x){
                j--;
            }
            if(i<j){
                arr[i] = arr[j];
                i++;
            }
            // 由前往后找比他大或等于的数,找到后填到前一个坑中
            while(i<j&&arr[i]<x){
                i++;
            }
            if(i<j){
                arr[j]=arr[i];
                j--;
            }
            arr[i] = x; //把基本数填到最后一个坑中
        }

        return i;
    }
}

归并排序

merge and sort

将初始序列看做n个长度为1 的有序子序列,两两归并

(有bug)

package com.array.arraysort;


import java.util.Arrays;

public class MergeSort {
    public static void main(String[] args) {
        //int[] arr = {2,1,34,5,7,56,3,23};
        int[] arr = {4,6,7,9,56,3,5,8,10,45};
        // 拆分
        split(arr,0,arr.length-1);
        // 归并
        //merge(arr,0,arr.length/2-1,arr.length-1);
        System.out.println(Arrays.toString(arr));

    }

    private static void split(int[] arr,int start,int end) {
        // 计算中间索引
        int middle = (start+end)/2;
        if(start<end){
            split(arr,start,middle);
            split(arr,middle+1,end);
            merge(arr,start,middle,end);
        }
    }

    private static void merge(int[] arr, int start, int middle, int end) {
        // 定义一个临时数组
        int[] temp = new int[end-start+1];
        // 定义左边数组的起始索引
        int i = start;
        // 定义右边数组的起始索引
        int j = middle+1;
        // 定义临时数组的起始索引
        int index = 0;
        // 比较左右两个数组的元素大小,往临时数组中放
        while(i<=middle&&j<=end){
            if(arr[i]<=arr[j]){
                temp[index]=arr[i];
                i++;
            }else{
                temp[index] = arr[j];
                j++;
            }
            index++;
        }
        // 处理剩余元素
        while(i<=middle){
            temp[index] = arr[i];
            i++;
            index++;
        }
        while(j<end){
            temp[index] = arr[j];
            j++;
            index++;
        }
        // 将临时数组中的元素取到原数组中
        for(int k = 0;k<temp.length;k++){
            arr[k+start]=temp[k];
        }
    }
}

基数排序

分配 + 收集,又名桶排序

  1. 先按照各位数分配
  2. 将桶中的数据取出(从前往后,从上往下)
  3. 按照十位的数字分配
  4. 将桶中的数据取出
  5. 按照百位的数字再进行分配
  6. 重复(数字最高位次即可完成排序)
package com.array.arraysort;


import java.util.Arrays;

// bucket sort
public class BucketSort {
    public static void main(String[] args) {
        // assign and collect
        int[] arr = {1,34,5,23,6,7,9,324,5346,43,214,4,324,5};
        // determine sort time
        // get the largest number in the arr
        //int max = getMax(arr);
        // bucket sort
        sortArray(arr);
        System.out.println(Arrays.toString(arr));

    }

    private static void sortArray(int[] arr) {
        // define 10 buckets using 2d array
        int[][] temp = new int[10][arr.length];
        // define an array to count
        int[] counts = new int[10];
        int max = getMax(arr);
        int len = String.valueOf(max).length();
        // loop
        for(int i = 0,n=1;i<len;i++,n*=10){
            for (int j = 0; j < arr.length; j++) {
                // get each number
                int remainder = arr[j]/n%10;
                temp[remainder][counts[remainder]++] = arr[j];
            }
            // get element in the buckets;
            int index = 0;
            for (int k = 0; k < counts.length; k++) {
                if(counts[k]!=0){
                    for (int h = 0; h < counts[k]; h++) {
                        // get ele from buckets, put into original bucket
                        arr[index] = temp[k][h];
                        index++;
                    }
                    counts[k] = 0; // clear last count number
                }
            }

        }

    }

    private static int getMax(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }
    
}

堆排序

是一种选择排序

基本思想

  1. 将待排序序列构成一个大顶堆,此时,整个序列的最大值就是堆顶的根结点
  2. 将其与末尾元素进行交换,此时末尾就为最大值
  3. 然后将剩余 n-1 个元素重新构造成一个堆,这样就会得到n个元素的次小值
  4. 如此反复执行,便能得到一个有序序列

大顶堆:父结点大于等于左右子节点

小顶堆:父结点小于等于左右子节点

// big top heap; ascenfing
arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2];
// small top heap; descending
arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

将数组看为完全二叉树 —> 转成大顶堆

从最后一个非叶子结点开始转  
如果其子节点大于该节点,则交换,否则不动
保证每一个子树都满足大顶堆

根结点的元素和最后一个节点进行换位

对除了当前数的最后一个元素(即整个树的最大值)之外的树进行大顶堆的调整

循环
package com.array.arraysort;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        // define an array
        int[] arr = {1,34,5,23,6,7,9,324,5346,43,214,4,324,5};
        // adjust to big top heap
        // toMaxHeap(arr,arr.length,1);
        // 定义开始调整的位置
        int startIndex = (arr.length-1)/2; // 最后一个非叶子节点
        // 循环开始调
        for (int i = startIndex; i >= 0; i--) {
           toMaxHeap(arr,arr.length,i);
        }
        System.out.println(Arrays.toString(arr));
        // 经过上面的操作,已经把数组变成了一个大顶堆
        // 把跟元素和最后一个元素进行调换
        for (int i = arr.length-1;i>0;i--){
            // 进行调换
            int t = arr[0];
            arr[0] = arr[i];
            arr[i] = t;
            // 换完之后,再把剩余元素换成大顶堆
            toMaxHeap(arr,i,0);
        }
        System.out.println(Arrays.toString(arr));

    }

    /**
     * @param arr 要排序的数组;
     * @param size 调整的元素个数
     * @param index 从哪里开始调整
     */
    private static void toMaxHeap(int[] arr, int size, int index) {
        // 获取左右子节点的索引
        int leftNodeIndex = index * 2 + 1;
        int rightNodeIndex = index * 2 + 2;
        // 查找最大节点所对应的索引
        int maxIndex = index;
        if(leftNodeIndex<size && arr[leftNodeIndex] > arr[maxIndex]){
            maxIndex = leftNodeIndex;
        }
        if(rightNodeIndex<size && arr[rightNodeIndex] > arr[maxIndex]){
            maxIndex = rightNodeIndex;
        }
        // 调换位置
        if(maxIndex != index){
            int t = arr[maxIndex];
            arr[maxIndex] = arr[index];
            arr[index] = t;
            // 调换完之后可能会影响到下面的子树,不是大顶堆
            toMaxHeap(arr,size,maxIndex);
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值