排序一--基础排序

来源:互联网 发布:室内设计画图软件 编辑:程序博客网 时间:2024/05/21 22:58

 


冒泡排序:具体算法描述如下:

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

 

分类   排序算法
数据结构  数组
最差时间复杂度  О(n2)
最优时间复杂度  О(n)
平均时间复杂度  О(n2)
最差空间复杂度 О(n) total, O(1) auxiliary

 

  /**     * 冒泡排序     */    public void maoPao() {        int[] nums = new int[]{8, 9, 2, 1, 4, 3, 5, 7, 6, 0};        for (int i = 0; i < nums.length - 1; i++) {            for (int j = i; j < nums.length; j++) {                if (nums[i] > nums[j]) {                    int temp = nums[i];                    nums[i] = nums[j];                    nums[j] = temp;                }            }        }        print(nums);    }


 


简单选择排序    


1、从第一个元素开始,循环
2、定义一个最小值索引记录 minIndex, 为当前值索引 i。
3、(当前minIndex元素 X ) 对比 剩余未排序的其他元素。
4、如果发现有小于X的元素,则将该值索引标记为 minIndex
5、重复步骤3,4后,交换 minIndex 和 i 的值。

分类   排序算法
数据结构  数组
最差时间复杂度  О(n2)
最优时间复杂度  О(n2)
平均时间复杂度  О(n2)
最差空间复杂度 О(n) total, O(1) auxiliary

选择排序的交换操作介于和次之间。选择排序的比较操作为次之间。选择排序的赋值操作介于和次之间。
比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。 交换次数O(n),最好情况是,已经有序,交换0次;最坏情况是,逆序,交换n-1次。 交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。

 

    /**     * 简单选择排序     */    public void simpleSelect() {        int[] nums = new int[]{8, 9, 2, 1, 4, 3, 5, 7, 6, 0};        for (int i = 0; i < nums.length - 1; i++) {            int min = i;            for (int j = i; j < nums.length; j++) {                if (nums[min] > nums[j]) {                    min = j;                }            }            if (min != i) {                int temp = nums[i];                nums[i] = nums[min];                nums[min] = temp;            }        }        print(nums);    }


 

 

 

插入排序:具体算法描述如下:


1、从第一个元素开始,该元素可以认为已经被排序
2、取出下一个元素,在已经排序的元素序列中从后向前扫描
3、如果该元素(已排序)大于新元素,将该元素移到下一位置
3、重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
4、将新元素插入到该位置后
5、重复步骤2~5

平均来说插入排序算法复杂度为O(n2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择

 /**     * 插值排序     */    public void insert() {        int[] nums = new int[]{8, 9, 2, 1, 4, 3, 5, 7, 6, 0};        for (int i = 1; i < nums.length; i++) {            int j = i;            int data = nums[i];            while (j > 0 && nums[j - 1] > data) {                nums[j] = nums[j - 1];                j--;            }            nums[j] = data;        }        print(nums);    }


 

希尔排序:


 核心:先将序列分成较多个子序列分别进行排序,再分成较少个子序列分别进行排序,直到最后为一个序列排序。
 形象的说:比如先分成  8  个子序分别排序,再 4  个子序,再 2 个子序,最后 1 个(1个也就是全部序列啦)。

 算法的最后一步就是普通的插入排序


 在大数组中表现优异的步长串行是(斐波那契数列除去0和1将剩余的数以黄金分区比的两倍的幂进行运算得到的数列):

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,


 (1, 9, 34, 182, 836, 4025, 19001, 90358, 428481, 2034035, 9651787, 45806244, 217378076, 1031612713, …)

各类步长公式

 

 

    public void shell() {        int[] nums = new int[]{8, 9, 2, 1, 4, 3, 5, 7, 6, 0};        int seg = 1;        while (seg < nums.length / 3) seg = seg * 3 + 1;    // <O(n^(3/2)) by Knuth,1973>: 1, 4, 13, 40, 121, ...每次的步长。        for (; seg >= 1; seg /= 3) {            for (int i = seg; i < nums.length; i++) {  //插入排序外皮开始, 以seq为递增                int j = i;                int data = nums[i];                while (j > (seg - 1) && nums[j - seg] > data) {                    nums[j] = nums[j - seg];                    j -= seg;                }                nums[j] = data;            }        }        print(nums);    }


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0