JAVA排序算法总结

不要独享荣耀。独享荣耀,有天就会独吞苦果。

 

1.冒泡排序

说到排序算法最先想到的就是冒泡排序了,它是最简单也是最慢的排序方法,双层for循环对每两项数值进行比较交换

/**
     * 冒泡排序
     * @param array
     */
    public static void maoPao(int []array){
        int temp;
        for(int i=1;i<array.length;i++) {
            for(int j=0;j<array.length-1-i;j++) {
                if(array[j]>array[j+1]) {
                    temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                }
            }
        }
        for(int i=0;i<array.length;i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }

 

2.选择排序

循环遍历整个数组,不断把最小的值放到前面

/**
     * 选择排序
     * @param array
     */
    public static void xuanZe(int []array) {
        int index,temp;
        for(int i=0;i<array.length-1;i++) {
            index=i;//用来记住数组元素的下标
            for(int j=i+1;j<array.length;j++) {
                if(array[index]>array[j]) {
                    index=j;//只对index值改变,不交换元素位置
                }
            }
            if(i!=index) {
                temp=array[index];
                array[index]=array[i];
                array[i]=temp;
            }//一轮排序进行一次数组位置交换
            System.out.print("第"+i+"次:");
        }
        for(int i=0;i<array.length;i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }

 

3.插入排序

遍历整个数组,不断插入较小的数字到已排好顺序的部分中

/**
     * 插入排序
     * @param array
     */
    public static void chaRu(int []array) {
        int temp;
        for(int i=1;i<array.length;i++) {
            int j=i;
            temp = array[i];
            while( j>0 && temp < array[j-1]) {
                array[j] = array[j-1];
                j--;
            }
            array[j] = temp;
        }
        for(int i=0;i<array.length;i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }

 

4.快速排序

采用分治的思想,先取中间值,分别从双端比较,把左端换成都比中间值小的,右端都比中间值大,然后重复此操作

/**
     * 快速排序
     * @param array
     * @param left
     * @param right
     */
    public static void kuaiSu(int []array,int left,int right){
        if(left < right) {
            int i=left,j=right;
            int pivot = array[left];//选择最左边的元素作为中间值

            /**
             * 分治
             */
            while(i < j) {
                while(i < j && array[j] >= pivot) {
                    j--;
                }
                if(i < j) {
                    array[i] = array[j];
                    i++;
                }
                while(i < j&& array[i] < pivot){
                    i++;
                }
                if(i < j) {
                    array [j] =array [i];
                    j--;
                }
            }
            array [i]=pivot;
            //递归
            kuaiSu(array,left,i-1);
            kuaiSu(array,i+1,right);
        }
    }

 

如果你看不懂这张图可以看看这个漫画坐在马桶上看算法

5.二分查找排序

与直接插入一样,只是找合适的插入位置的方式不同,这里是按照二分法找到合适的位置,可以减少比较的次数

/**
     * 二分查找插入排序
     * @param a
     */
    public static void erFenChaZhao(int[] a){
        for(int i = 0;i < a.length;i++){
            int temp = a[i];
            int left = 0;
            int right = i-1;
            int mid = 0;
            while(left <= right){
                mid = (left+right)/2;
                if(temp<a[mid]){
                    right = mid-1;
                }else{
                    left = mid+1;
                }
            }
            for(int j = i-1;j >= left; j--){
                a[j+1] = a[j];
            }

            if(left != i){
                a[left] = temp;
            }
        }
    }

6.希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
先取一个正整数d1 < n, 把所有相隔d1的记录放一组,每个组内进行直接插入排序;然后d2 < d1,重复上述分组和排序操作;直至di = 1,即所有记录放进一个组中排序为止。

/**
     * 希尔排序
     * @param array
     */
/**
* 希尔排序的原理:根据需求,如果你想要结果从小到大排列,它会首先将数组进行分
组,然后将较小值移到前面,较大值
* 移到后面,最后将整个数组进行插入排序,这样比起一开始就用插入排序减少了数
据交换和移动的次数,
* 可以说希尔排序是加强 版的插入排序 拿数组5, 2,8, 9, 1, 3,4来说,数组长
度为7,当increment为3时,数组分为两个序列
* 5,2,8和9,1,3,4,第一次排序,9和5比较,1和2比较,3和8比较,4和比其
下标值小increment的数组值相比较
* 此例子是按照从小到大排列,所以小的会排在前面,第一次排序后数组为5, 1, 3,
4, 2, 8,9
* 第一次后increment的值变为3/2=1,此时对数组进行插入排序, 实现数组从大到
小排
*/
    public static void xiEr(int[] array){
        int d = array.length;
        while(true){
            d = d/2;
            for(int x = 0;x<d;x++){
                for(int i = x+d;i<array.length;i=i+d){
                    int temp = array[i];
                    int j;
                    for(j = i-d;j>=0;j--){
                        array[j+d]=array[j];
                    }
                    array[j+d] = temp;
                }
            }
            if(d == 1){
                break;
            }
        }
        System.out.println(Arrays.toString(array));
    }

7.堆排序

堆排序是一种树形选择排序,是对直接选择排序的有效改进。
堆的定义下:具有n个元素的序列 (h1,h2,...,hn),当且仅当满足
(hi>=h2i,hi>=h2i+1)或(hi<=h2i,hi<=h2i+1) (i=1,2,...,n/2)时称之为堆。在这里
只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为
最大项(大顶堆)。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左
子树、右子树。
思想:初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储
序,使之成为一个 堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节
点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点
的堆,并对 它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排
序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排
序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函
数。

/**
     * 堆排序
     * @param array
     */
    public static void HeapSort(int[] array){
        for(int i=0;i<array.length-1;i++){
            //建堆
            buildMaxHeap(array,array.length-1-i);
            //交换堆顶和最后一个元素
            swap(array,0,array.length-1-i);
        }
        System.out.println(Arrays.toString(array));
    }

    public static void buildMaxHeap(int[] data,int lastIndex){
        //从lastIndex处节点(最后一个节点)的父节点开始
        for(int i = (lastIndex-1)/2;i>=0;i--){
            //k保存正在判断的节点
            int k = i;
            //如果k节点的子节点存在
            while(k*2+1<=lastIndex){
                //将k点左子节点的索引赋值给biggerIndex
                int biggerIndex = 2*k+1;
                //如果biggerIndex小于lastIndex,代表k节点的右子节点存在
                if(biggerIndex < lastIndex){
                    //如果右子节点的值较大
                    if(data[biggerIndex]<data[biggerIndex+1]){
                        //biggerIndex总是记录较大子节点的索引
                        biggerIndex++;
                    }
                }
                //如果k节点的值小于其较大子节点的值
                if(data[k] < data[biggerIndex]){
                    //交换他们
                    swap(data,k,biggerIndex);
                    //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                    k = biggerIndex;
                } else {
                    break;
                }
            }
        }
    }

    private static void swap(int[] data,int i,int j){
        int tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
    }

8.归并排序

归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

/**
     * 归并排序
     * @param array
     */
    public static void mergingSort(int[] array) {
        sort(array, 0, array.length - 1);
        System.out.println(Arrays.toString(array) + " mergingSort");
    }

    private static void sort(int[] data, int left, int right) {
        if (left < right) {
            //找出中间索引
            int center = (left + right) / 2;
            //对左边数组进行递归
            sort(data, left, center);
            //对右边数组进行递归
            sort(data, center + 1, right);
            //合并
            merge(data, left, center, right);
        }
    }

    private static void merge(int[] data, int left, int center, int right) {
        int[] tmpArr = new int[data.length];
        int mid = center + 1;
        //third记录中间数组的索引
        int third = left;
        int tmp = left;
        while (left <= center && mid <= right) {
            //从两个数组中取出最小的放入中间数组
            if (data[left] <= data[mid]) {
                tmpArr[third++] = data[left++];
            } else {
                tmpArr[third++] = data[mid++];
            }
        }

        //剩余部分依次放入中间数组
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }

        while (left <= center) {
            tmpArr[third++] = data[left++];
        }

        //将中间数组中的内容复制回原数组
        while (tmp <= right) {
            data[tmp] = tmpArr[tmp++];
        }
    }

 9.基数排序

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

/**
     * 基数排序
     * @param array
     */
    public static void radixSort(int[] array) {
        //首先确定排序的趟数;
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
        }
        int time = 0;
        //判断位数;
        while (max > 0) {
            max /= 10;
            time++;
        }


        //建立10个队列;
        ArrayList<ArrayList<Integer>> queue = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ArrayList<Integer> queue1 = new ArrayList<>();
            queue.add(queue1);
        }


        //进行time次分配和收集;
        for (int i = 0; i < time; i++) {
            //分配数组元素;
            for (int anArray : array) {
                //得到数字的第time+1位数;
                int x = anArray % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                ArrayList<Integer> queue2 = queue.get(x);
                queue2.add(anArray);
                queue.set(x, queue2);
            }
            int count = 0;//元素计数器;
            //收集队列元素;
            for (int k = 0; k < 10; k++) {
                while (queue.get(k).size() > 0) {
                    ArrayList<Integer> queue3 = queue.get(k);
                    array[count] = queue3.get(0);
                    queue3.remove(0);
                    count++;
                }
            }
        }
        System.out.println(Arrays.toString(array) + " radixSort");
    }

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幽蓝丶流月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值