Java数组排序

数组排序-八种数组的排序方法解释说明案例

基本查找

直接通过for循环,获得数值所对应的索引值。

二分查找

通过二分法来查找数据能能大大的提高效率,数组要求必须是按顺序排序。寻找数据时从中间开始判断,如果数据比中间值小,则查找范围最大值缩小为中间索引-1,反之,查找范围最小值缩小为中间索引+1,重复操作获取数值所对应的索引。

//二分法
//把数据分成两半进行排序
public class ArrayDichotomy {
    public static void main(String[] args) {
        int arry[] = new int[]{10,20,30,40,50,60,70,80,90};
        int index = getIndex(arry, 10);
        System.out.println(index);
    }

    private static int getIndex(int[] arry, int i) {
        int minIndex=0;
        int maxIndex=arry.length-1;
        int centerIndex=(minIndex+maxIndex)/2;

        while (minIndex<=maxIndex){
            if (i == arry[centerIndex]){
                return centerIndex;
            }else if (i>arry[centerIndex]){
                minIndex=centerIndex+1;
            }else if (i<arry[centerIndex]){
                maxIndex=centerIndex-1;
            }
            centerIndex=(minIndex+maxIndex)/2;
       }
       //没找到返回-1
       return -1;
    }
}

①冒泡排序

Java最经典的排序方式,简单来说就是每一个数据与后面的数据两两进行比较,如果比它大或小就换位置,一轮后最大或者最小的数就出现在最后一个数,反复循环,可以把数据从大到小或从小到大进行排列。

//冒泡法
//数据两两比较,大的数据和小的数据换位置
public class ArrayBubble {
    public static void main(String[] args) {
        int[] arry = new int[]{1,4,543,67,268,7845,-1};
        for (int i = 0; i < arry.length-1; i++) {
            for (int j = 0; j < arry.length-1-i; j++) {
                if (arry[j]>arry[j+1]){
                    int t = arry[j+1];
                    arry[j+1] = arry[j];
                    arry[j] = t;
                }
            }
        }
        System.out.println(Arrays.toString(arry));
    }
}

②选择排序

对数组元素直接进行比较,用第一个数依次和后面的数比较,如果数值比第一个数小则交换位置,一轮后数组中的最小值出现在第一位,重复循环,可以把数组从小到大进行排序。

//选择排序
//从0开始,依次和后面的元素进行比较,小的放前面,一轮后最小的在最前面
public class ArrayChoose {
    public static void main(String[] args) {
        int[] array = new int[]{24,69,80,53,45};
        for (int j = 0; j < array.length - 1; j++) {
            for (int i = 1+j; i < array.length; i++) {
                if (array[j]>array[i]){
                    int t = array[j];
                    array[j] = array[i];
                    array[i] = t;
                }
            }

        }
        System.out.println(Arrays.toString(array));


    }
}

③直接插入排序

把第一个数据看成一个数组,里面只有一个元素,然后循环循环整个数组,当发现第二个元素比第一个小时,把元素插入到第一个元素的左边,然后插入第三个元素时依次和前面的元素判断,判断是插入两者的左边、中间、右边,反复上述过程,完成数组的排序。

//直接插入排序
//将一个记录插入到长度为m的有序表中,使之保持有序
public class ArrayDirectInsertion {
    public static void main(String[] args) {
        int[] array = new int[]{49,38,358,541,3896};

        //方法一
        //循环表示要进行的次数
        /*for (int i = 1; i < array.length; i++) {
        //这里定义j的存在是因为当元素数量大于2时,就要判断三者之间的关系,而不仅仅于一个元素的左还是右
            int j=i;
            //如果数据比第一个小,两个互换位置
            while (j>0&&array[j]<array[j-1]){
                int t=array[j];
                array[j]=array[j-1];
                array[j-1]=t;
                j--;
            }
        }*/
        //方法二
        for (int i = 1; i < array.length; i++) {
            for (int j = i; j >0 ; j--) {
                if (array[j]<array[j-1]){
                    int t=array[j];
                    array[j]=array[j-1];
                    array[j-1]=t;
                }
            }
        }
        System.out.println(Arrays.toString(array));
    }
}

④希尔排序

希尔排序是对直接插入排序的优化,简单来说,就是以一定的间隔来进行元素大小判断,从而简化一些大小判断过程。核心思想就是合理的选取增量,就会让序列大致有序。

//希尔排序
//对直接插入排序的优化 核心思想就是合理的选取增量 就会让序列大致有序
//然后再不断的缩小增量,进行插入排序,直到增量为1
import java.util.Arrays;

public class ArrayShell {
    public static void main(String[] args) {

        int[] array = new int[]{46,55,13,42,17,94,5,70};

        //Knuth 克努特 序列选取间隔 提高效率
        int jiange = 1;
        while (jiange<= array.length/3){
            jiange = jiange*3+1;
        }

        for (int h =jiange; h>0; h=(h-1)/3){
            for (int i = h; i <array.length; i++) {
                for (int j = i; j >h-1 ; j-=h) {
                    if (array[j]<array[j-h]){
                        int t=array[j];
                        array[j]=array[j-h];
                        array[j-h]=t;
                    }
                }
            }
        }
        System.out.println(Arrays.toString(array));
    }
}

⑤快速排序

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

//快速排序算法
//分治法:比大小,再分区
public class ArrayQuick {
    public static void main(String[] args) {
        int[] arr = new int[]{10,3,5,6,1,0,100,40,50,8};
        quickSort(arr,0, arr.length-1);
        System.out.println(Arrays.toString(arr));

    }

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

        }
    }

    //将基准数挖出形成第一个坑
    //由后向前找比他小的数,找到后挖出此数填到前一个坑中
    //由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中
    //执行2.3步骤
    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;
    }
}

⑥归并排序

//归并排序
public class ArrayMerge {
    public static void main(String[] args) {

        //原始待排序数组
        int[] arr = {10,30,2,1,0,8,7,2,5,10,20};

        //int[] arr = {4,5,7,8,1,2,3,6};
        //拆分
        chaiFen(arr,0,arr.length-1);


        //归并
        //guiBing(arr, 0, 3, arr.length-1);

        System.out.println(Arrays.toString(arr));
    }

    private static void chaiFen(int[] arr, int startIndex, int endIndex) {
        //计算中间索引
        int centerIndex = (startIndex+endIndex)/2;
        if (startIndex<endIndex){
            chaiFen(arr,startIndex,centerIndex);
            chaiFen(arr,centerIndex+1,endIndex);
            guiBing(arr,startIndex,centerIndex,endIndex);
        }
    }

    private static void guiBing(int[] arr, int startIndex, int centerIndex, int endIndex) {
        //定义一个临时数组
        int[] tempArr = new int[endIndex-startIndex+1];
        //定义左边数组起始索引
        int i = startIndex;
        //定义右边数组起始索引
        int j = centerIndex+1;
        //定义临时数组的起始索引
        int index = 0;
        //比较左右两个数组的元素大小,往临时数组放
        while (i<=centerIndex&&j<=endIndex){
            if (arr[i]<=arr[j]){
                tempArr[index] = arr[i];
                i++;
            }else {
                tempArr[index] = arr[j];
                j++;
            }
            index++;
        }
        //处理剩余元素
        while (i<=centerIndex){
            tempArr[index] = arr[i];
            i++;
            index++;
        }
        while (j<=endIndex){
            tempArr[index] = arr[j];
            j++;
            index++;
        }
//        System.out.println(Arrays.toString(tempArr));
        //将临时数组数据区取到原数组中
        for (int k = 0; k < tempArr.length; k++) {
            arr[k+startIndex] = tempArr[k];
        }
    }

}

⑦基数排序

//基数排序
public class ArrayRadix {
    public static void main(String[] args) {
        //基数排序通过分配再收集的方式进行排序
        int[] arr = {2,1,5,21,43,44,32,846,342234};
        //待确定的排序伦次
        //获取数组中的最大值
        //int max = getMax(arr);
        //基数排序
        sortArray(arr);

        System.out.println(Arrays.toString(arr));
    }

    private static void sortArray(int[] arr) {
        //定义二维数组,管理10个桶
        int[][] tempArr = new int[10][arr.length];
        //定义统计数组
        int[] count = new int[10];
        int max = getMax(arr);
        int len = String.valueOf(max).length();
        //循环伦次
        for (int i = 0,n=1; i < len; i++,n*=10) {
            for (int j = 0; j < arr.length; j++) {
                //获取每个位上的数字
                int last = arr[j]/n%10;
                tempArr[last][count[last]++] = arr[j];
            }
            //取出元素
            int index = 0;
            for (int k = 0; k < count.length; k++) {
                if (count[k]!=0){
                    for (int h = 0; h < count[k]; h++) {
                        //从桶中取出元素放回原数组
                        arr[index] = tempArr[k][h];
                        index++;
                    }
                    count[k] = 0;//清除上一次统计的个数
                }
            }
        }
    }

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

}

⑧堆排序

//堆排序
//通过将待排序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点 反复重复获取次最大值 最后完成排序
public class ArrayHeap {
    public static void main(String[] args) {
        int[] arr = {1, 0, 6, 7, 2, 3, 4};

        //调整成大顶堆的方法
        //定义开始调整的位置
        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));

    }

    //排序的数组 调整的元素个数 从哪里开始调整
    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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值