java-Android-常用十大排序算法

排序就是将一组对象按照某种逻辑顺序重新排列的过程。比如,订单按照日期排序的——这种排序很可能使用了某种排序算法。现在计算机的广泛使用使得数据无处不在,而整理数据的第一步通常就是进行排序。

学习排序算法三大实际意义

  1. IT从业人员必备技能,也是互联网公司面试的必考点
  2. 其中包含的技术和思想也能有效解决其他类型的问题
  3. 排序算法常常是我们解决其他问题的第一步
    图片来源于网络
    十大排序算法:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序、希尔排序、计数排序,基数排序,桶排序

一、冒泡排序算法

一种简单的排序算法。它反复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。这个工作重复地进行直到没有元素再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为元素会经由交换慢慢“浮”到数列的顶端。

具体步骤
  1. 从数组头开始,比较相邻的元素。如果第一个比第二个大(小),就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到尾部的最后一对,这样在最后的元素应该会是最大(小)的数;
  3. 重复步骤1~2,重复次数等于数组的长度,直到排序完成
原理图如下

image.png

代码如下
public static int[] sort(int[] array) {  
        if (array.length == 0)  
            return array;  
        /*循环数组长度的次数*/  
        for (int i = 0; i < array.length; i++){  
            /*从第0个元素开始,依次和后面的元素进行比较 
             * j < array.length - 1 - i表示第[array.length - 1 - i] 
             * 个元素已经冒泡到了合适的位置,无需进行比较,可以减少比较次数*/  
            for (int j = 0; j < array.length - 1 - i; j++){  
                /*如果第j个元素比后面的第j+1元素大,交换两者的位置*/  
                if (array[j + 1] < array[j]) {  
                    int temp = array[j + 1];  
                    array[j + 1] = array[j];  
                    array[j] = temp;  
                }  
                PrintArray.print(array);  
            }  
            System.out.println("---------------");  
            //PrintArray.print(array);  
        }  
  
        return array;  
    }  

二、简单选择排序

选择排序的思想其实和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面。但是过程不同,冒泡排序是通过相邻的比较和交换。而选择排序是通过对整体的选择。
其实选择排序可以看成冒泡排序的优化,因为其目的相同,只是选择排序只有在确定了最小数的前提下才进行交换,大大减少了交换的次数。
举个例子,对5,3,8,6,4这个无序序列进行简单选择排序,首先要选择5以外的最小数来和5交换,也就是选择3和5交换,一次排序后就变成了3,5,8,6,4.对剩下的序列继续进行选择和交换,最终就会得到一个有序序列。

具体步骤
  1. 首先,找到数组中最大(小)的那个元素;
  2. 其次,将它和数组的第一个元素交换位置(如果第一个元素就是最大(小)元素那么它就和自己交换);
  3. 再次,在剩下的元素中找到最大(小)的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。
原理图如下

image.png

代码如下
public static int[] sort(int[] array) {
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++) {
            int minIndex=i;/*最小数的下标,每个循环开始总是假设第一个数最小*/
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) /*找到最小的数*/
                    minIndex = j; /*将最小数的索引保存*/
            }
            System.out.println("最小数为:"+array[minIndex]);
            /*交换最小数和i当前所指的元素*/
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
            PrintArray.print(array);
            System.out.println("---------------");
        }
        return array;
    }

三、简单插入排序

插入排序不是通过交换位置而是通过比较找到合适的位置插入元素来达到排序的目的的。相信大家都有过打扑克牌的经历,特别是牌数较大的。在分牌时可能要整理自己的牌,牌多的时候怎么整理呢?就是拿到一张牌,找到一个合适的位置插入。这个原理其实和插入排序是一样的。
举个例子,我们将要收到5,3,4,8,6这几张牌,我们先收到5这张牌,毫无疑问,这张牌的位置是正确的,没必要整理。接着收到了牌3,然后3要插到5前面,把5后移一位,变成3,5。接着又收到了牌4,现在我们会怎么做?把4插入到5前面,把5后移一位。

具体步骤
  1. 对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
  2. 为了给要插入的元素腾出空间,我们需要将插入位置之后的已排序元素在都向右移动一位。
    插入排序所需的时间取决于输入中元素的初始顺序。例如,对一个很大且其中的元素已经有序(或接近有序)的数组进行排序将会比对随机顺序的数组或是逆序数组进行排序要快得多。
    总的来说,插入排序对于部分有序的数组十分高效,也很适合小规模数组。
原理图如下

image.png

image.png

代码如下
public static int[] sort(int[] array) {
        if (array.length == 0)
            return array;
        int currentValue;/*当前待排序数据,该元素之前的元素均已被排序过*/
        for (int i = 0; i < array.length - 1; i++) {
            int preIndex = i;/*已被排序数据的索引*/
            currentValue = array[preIndex + 1];
            System.out.println("待排序元素索引:"+(i + 1)+",值为:" +currentValue+
                    ",已被排序数据的索引:"+preIndex);

            /*在已被排序过数据中倒序寻找合适的位置,如果当前待排序数据比比较的元素要小,
            将比较的元素元素后移一位*/
            while (preIndex >= 0 && currentValue < array[preIndex]) {
                //将当前元素后移一位
                array[preIndex + 1] = array[preIndex];
                preIndex--;
                PrintArray.print(array);
            }
            /*while循环结束时,说明已经找到了当前待排序数据的合适位置,插入*/
            array[preIndex + 1] = currentValue;
            System.out.println("本轮被插入排序后的数组");
            PrintArray.print(array);
            System.out.println("--------------------");
        }
        return array;
    }

四、希尔排序

一种基于插入排序的快速的排序算法(请大家先学习插入排序,了解基本的插入排序的思想。对于大规模乱序数组插入排序很慢,因为元素只能一点一点地从数组的一端移动到另一端。例如,如果主键最小的元素正好在数组的尽头,要将它挪到正确的位置就需要N-1 次移动。
希尔排序为了加快速度简单地改进了插入排序,也称为缩小增量排序,同时该算法是冲破O(n^2)的第一批算法之一。
希尔排序是把待排序数组按一定增量的分组,对每组使用直接插入排序算法排序;然后缩小增量继续分组排序,随着增量逐渐减少,每组包含的元素越来越多,当增量减至 1 时,整个数组恰被分成一组,排序便完成了。这个不断缩小的增量,就构成了一个增量序列。

原理图如下

image.png

image.png

希尔排序中的增量序列
  1. 在先前较大的增量下每个子序列的规模都不大,用直接插入排序效率都较高,尽管在随后的增量递减分组中子序列越来越大,由于整个序列的有序性也越来越明显,则排序效率依然较高。
  2. 从理论上说,只要一个数组是递减的,并且最后一个值是1,都可以作为增量序列使用。有没有一个步长序列,使得排序过程中所需的比较和移动次数相对较少,并且无论待排序列记录数有多少,算法的时间复杂度都能渐近最佳呢?但是目前从数学上来说,无法证明某个序列是“最好的”。
  3. 常用的增量序列
    希尔增量序列 :{N/2, (N / 2)/2, …, 1},其中N为原始数组的长度,这是最常用的序列,但却不是最好的
    Hibbard序列:{2^k-1, …, 3,1}
    Sedgewick序列: {… , 109 , 41 , 19 , 5,1}
代码如下
 public static int[] sort(int[] array) {
        int len = array.length;
        /*按增量分组后,每个分组中,temp代表当前待排序数据,该元素之前的元素均已被排序过*/
        /*gap指用来分组的增量,会依次递减*/
        int currentValue,
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值