本文章图片使用的是https://twocups.cn/index.php/2020/02/01/17/这个地址博客内的。
冒泡排序(Bubble Sort)
-
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
根据以上结论,代码如下:
上面代码是大的元素下沉,还有一种是小的元素上浮:
直接插入排序(Insertion Sort)
1、从数组第2个元素开始抽取元素。
2、把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。
3、继续选取第3,4,….n个元素,重复步骤 2 ,选择适当的位置插入。
左侧保持一个有序数组,右侧元素按照排序插入。
代码如下:
还有另一个版本:
希尔排序(Shell Sort)
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。
代码如下:
选择排序(Selection Sort)
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
代码如下:
堆排序(Heap Sort)
将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
先构建大顶堆:选择有子节点的节点进行构建
对局部的堆进行排序
将顶级节点放到最后,再次进行构建
快速排序(Quick Sort)
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
主程序
递归部分:
归并排序(Merge Sort)
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
代码:
基数排序(Radix Sort)
主要思想是对数组中所有元素先根据其个位进行排序,再根据其十位进行排序,之后是百位、千位,以此类推,直到最高位。
代码:
// ****** 8.基数排序 ******
public static int[] RadixSort(int[] arr){
if(arr.length == 0 || arr.length ==1)
return arr;
// max 指数组中最大的数,maxDigit 指这个最大的数是几位数
int max = arr[0];
for(int x:arr)
max = Math.max(x,max);
int maxDigit = 0;
while(max != 0){
max /= 10;
maxDigit++;
}
// mod 用于为数组中的数取余数,div 用于把通过 mod 取的余数变成个位数
int mod = 10;
int div = 1;
ArrayList<ArrayList<Integer>> bucket = new ArrayList<ArrayList<Integer>>();
for(int j = 0;j < 10;j++){
bucket.add(new ArrayList<Integer>());
}
for(int i = 0;i<maxDigit;i++,mod *= 10,div *= 10){
// 打印这一轮的排序结果
System.out.println(Arrays.toString(arr));
for(int j = 0;j < arr.length;j++){
// num 指当前元素 arr[j] 的个/十/百/千位是几
int num = (arr[j] % mod) / div;
bucket.get(num).add(arr[j]);
}
int index = 0;
for(int j = 0;j < 10;j++){
if(bucket.get(j).size() != 0){
for(int x:bucket.get(j))
arr[index++] = x;
// 将桶中所有的动态数组清空,否则第二次循环开始再用到这些动态数组时里面还会有数据
bucket.get(j).clear();
}
}
}
return arr;
}
计数排序(Counting Sort)
它的核心是将数组中的元素值转换为键存储在额外空间中。主要思想是额外创建一个数组,额外数组中元素下标是待排序数组中元素的值,而额外数组中的值是其下标的值在待排序数组中作为元素的值出现的次数。
代码:
桶排序(Bucket Sort)
桶排序是计数排序的升级版,也是非比较排序。主要思想是对数组中数值范围进行划分,数组中的每个元素根据其数值的所在范围,进入不同的“桶”。然后在不同的桶中分别对这些元素进行排序(直接插入排序),再依次输出。
代码:
根据计数排序,算出桶的个数,把数据放入桶内
桶内进行直接插入排序