九大排序,Java实现(附代码)
今天整理了一下九大排序,分享一波,以下例子都测试过,都进行升序排序
先从简单选择排序讲起:
简单选择排序,稳定
从待排序序列中选取一个最小的数,与当前序列最左边的数交换
如:
第一趟:在n个元素中选出最小的一个元素与数组0号索引上的元素交换,
第二趟:在剩下的 n - 1 个数中找到最小的数, 与第数组1号索引上的元素交换,
以此类推,n个元素需要选择 n - 1趟,序列全部有序
代码实现:
上述简单选择排序,每次遍历只维护一个最小值,与待排序序列的第一个位置交换,
优化:
2元选择排序, 每次遍历保存待排序数的最大值,和最小值
最小值与待排序序列最左边的元素交换, 最大值与最右边的元素交换
堆排序
堆排序,不稳定
选择排序的一种,就是每次选择一个最大(或最小)的值,
存放到正确的位置。
那么该如和选择呢:
堆排序核心思想:将待排序序列建成堆,得到最大(最小)值,存放到正确位置
首先知道使用数组存储一颗完全2叉树, 从0开始计数,
大顶堆:所有父节点元素的值 >= 两个子节点的值
那么 i 节点的左子节点为 2 * i + 1, 右子节点为 2 * i + 2;
我们把待排序序列建成一个大顶堆
从最后一个叶子节点的父节点((size - 1)/ 2)开始往前遍历,建立大顶堆,即,比较两个子节点的值,与父亲节点的值,如果子节点值大于父节点,则交换
第一趟找到 [0, data.length - 1]序列中最大的数存放到 data.length - 1
第一趟找到 [0, data.length - 2]序列中最大的数存放到 data.length - 2,
每次取得最大值,都需要从下往上交换 , 以此类推得到有序序列
代码
冒泡排序, 稳定:
交换排序的一种,比较相邻的元素,如果左边的元素大于右边的元素,就交换他们两个。
每一趟交换,都在待排序数中找到最大的元素,
存放在最待排序数中的最右边
10个元素第一趟时需比较9次,将最大的元素移动到最后一位
第2趟时,待排序数变为9个,需比较8次, 找到第2大的数,存放在倒数第2为,以此类推
代码
快速排序, 不稳定:
使用递归分治思想, 交换排序的一种
选择一个基准数,通常选择第一个元素或者最后一个元素
经过一趟排序后,左边一部分比基准数小,右边一部分比基准数大
将基准数存放至交界位置
然后分别对这两部分进行同样的排序,直到每部分元素个数为1,则此时整个序列有序
简单插入排序,稳定
初始时,第0号元素默认有序, 从第1号元素开始,往前搜索,找到正确的位置
希尔排序,缩小增量排序, 不稳定
每趟排序根据增量scan, 将待排序序列分为scan组,在组内进行直接插入排序。一趟后,每个组内有序,再缩小增量继续分组排序,直至增量为1,整个序列有序
代码:
归并排序,稳定
过程分为:先拆分,再归并
拆分:即每次将待排序序列分为两部分
归并: 当每部分拆分至只有一个元素时,此时每部分都有序,两两开始归并,
归并两个有序序列的时间复杂度为 O(n)
代码:
那么最后还有两个接近线性的排序算法,虽然并不是,hhhh
桶排序, 稳定
桶排序, 稳定
需要k(当前数组的最大值)个辅助空间, 将当前数组中的元素与计数数组的下标对应
即将对应下标的值加一, count[data[i]]++;
若要得到得到升序序列,从左向右遍历, 若要得到降序序列从右往左遍历即可优化:可将计数数组的长度设为 max - min + 1, 那么需要多维护一个原数组的最小值
要保证稳定性,需对计数数组,从后往前遍历
若需要降低空间复杂度可以将一组数,放入一个桶中,
再对桶中的元素(桶中可使用其他排序方法)
在当待排序数组内有大量重复的数值并且这些数值较为集中时,使用桶排序效率较好,基本达到O(n)
代码:
基数排序:
基数排序, 桶排序的延伸
对数字的每位进行桶排序
代码:
对exp位进行桶排序(1代表个位, 10代表十位,以此类推)