一、排序算法概述
所谓排序,即按照一定规则对数据进行排列,比如递增或递减的方式,实现这种排列的算法就是排序算法了,而常见的排序算法分类标准有:内部排序和外部排序。内部排序是数据记录在内存中进行排序,外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
常见的内部排序算法有八种:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。外部排序的话,采用多路归并排序算法,将文件划分为几个能读入内存的小部分,然后分别读入进行排序,经过多次处理即可完成对大文件的排序。排序算法的大致分类如图所示:
实际应用中,内部排序的对象是整数,而排序的规则包括从小到大排序和从大到小排序,每一种排序算法都有其各自的特点,在特定的场合也有着不错的执行效率,后面会一一进行分析和整理,以数组元素为例,先看一下交换排序。
二、冒泡排序
它是一种最简单、最直观的排序方式,属于交换排序,整个排序过程就像水泡的浮起过程一样,故因此而得名冒泡排序。核心思路是相邻的数据进行交换达到排序目的。
冒泡排序的步骤大致如下:
1). 从一开始,对前后相邻的元素去比较,若前面的元素大于后面的元素,则交换二者的位置。
2). 针对所有的元素重复上述步骤,直到从小到大的完成排序。
Demo演示:
public class ArraySortDemo{
/** 以整形数组为例测试 */
public static void main(String[] args) {
int[] arr = {4, 3, 7, 89, 23, 6, 20, 15, 32, 35};
int[] result = bubbleSort(arr);
for (int i = 0; i < result.length - 1; i++) {
System.out.print(" " + result[i]); // 3 4 6 7 15 20 23 32 35 89
}
}
/** 冒泡排序 */
public static int[] bubbleSort(int[] num) {
for (int i = 0; i < num.length - 1; i++) {
for (int j = 0; j < num.length - 1 - i; j++) {
// 相邻的元素进行比较
if (num[j] > num[j + 1]) {
// 使用临时变量交换元素
int temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
}
}
}
return num;
}
}
优缺点分析:
- 优点:就是简单、直观,空间复杂度较低,是一种稳定排序。
- 缺点:时间复杂度较高,排序速度慢。
三、快速排序
它可看作是冒泡排序的改进版,也属于交换排序,核心思路是将数据按照基准值划分为两部分,小于基准值的放在一边,大于基准值的放在另一边,然后再选择一个基准值多次递归上述操作,最终达到交换排序目的。因此,快速排序利用的是分治思想和递归思想。
快速排序的步骤大致如下:
1). 选定一个分界值作为基准,将数组一分为二。
2). 数组的所有元素比基准值小的会放在基准的左边,所有元素比基准值大的会在基准的右边。
3). 基准的左边和基准的右边又可以各选定一个分界值作为基准,继续排序,递归的进行上述过程,最终整个数组就会按从小到大顺序完成排序。
Demo演示:
public class ArraySortDemo{
/** 快速排序测试 */
public static void main(String[] args) {
int[] num = {9, 18, 7, 99, 43, 66, 10, 12, 2, 45};
fast(num, 0, num.length - 1);
}
/** 对数组 或数组指定范围的元素进行快速排序 */
public static void fast(int[] arry, int first, int last) {
if (last > first) {
// 选择基准值
int pivotIndex = fastvoid(arry, first, last);
// 前半部分
fast(arry, first, pivotIndex - 1);
// 后半部分
fast(arry, pivotIndex + 1, last);
}
}
/** 从前向后和从后向前依次和主元比较,当前面的元素比主元大,后面的元素比主元小则这两个元素互换位置 */
public static int fastvoid(int[] arry, int first, int last) {
int privot = arry[first];
int low = first + 1;
int high = last;
while (low < high) {
while (low <= high && arry[low] <= privot) {
low++;
}
while (low <= high && arry[high] >= privot) {
high--;
}
if (high > low) {
int temp = arry[high];
arry[high] = arry[low];
arry[low] = temp;
}
}
while (high > first && arry[high] >= privot) {
high--;
}
if (privot > arry[high]) {
arry[first] = arry[high];
arry[high] = privot;
return high;
} else {
return first;
}
}
}
优缺点分析:
- 优点:作为冒泡排序的改进版,基于分治策略和递归策略,时间复杂度较低,排序速度快。
- 缺点:是一种不稳定排序。
小结
排序算法是基本的算法的一部分,常见的排序算法有上面罗列的八种内部算法,学习和掌握它们的核心思路最为重要,这里,先重点整理了两种交换排序的算法。
参考:《Java常用算法手册(第3版)》+ 百度图片