常见排序算法
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。
参考: 十大排序算法比较
1 插入排序
构建有效序列,对未排序的数据依次与已排序的数据比较,找到相应位置并插入
/**
* 插入排序
* 1.将第一元素看作有序序列
* 2.取出下一个元素,在已排序的序列从后向前扫描
* 3.比较:该元素大于新元素(未排序),则将该元素移到下一位置
* 4.重复3,直到找到该元素<=新元素,将新元素插入到该位置
* 稳定排序
* @param array
*/
public static void insertSort(int[] array) {
int length = array.length;
int temp = 0;
//从第二个元素(1)开始
for (int i = 1; i < length; i++) {
//当前循环要排序的数据
temp = array[i];
for (int j = i; j >= 0; j--) {
//第一个元素,特殊处理
if(j == 0){
array[j] = temp;
break;
}
//数据array[j-1]小于之前的数据时,将此数据后移一位
if(temp < array[j-1]) {
array[j] = array[j-1];
}else {
array[j] = temp;
break;
}
}
}
}
2 冒泡排序
重复比较相邻的数据,如果顺序不对,就交换它们的位置,直到最后一组
/**
* 冒泡排序法
* 稳定排序
* @param array
*/
public static void bubbleSort(int[] array) {
int t = 0;
//外层循环,每一趟将相对最大的数据放在后面
for (int i = 0; i < array.length - 1; i++) {
//内层循环,比较相邻数据,最终把最大的元素放在后面
for (int j = 0; j < array.length -1 - i; j++) {
if(array[j] > array[j+1]){
t = array[j];
array[j] = array[j+1];
array[j+1] = t;
}
}
}
}
3 快速排序
选定一个基准值,将比基准值小的排到左侧,大的排到右边,再分别对两部分进行排序,直到整个序列有序
ps:为方便理解,随便定义一个概念
空位:即赋值过程中值被赋予其它位置的数据所在位置,此时该位置数据已被复制,因此变得可有可无,可视为空
/**
* 快速排序
* 不稳定排序
* @param array
*/
public static void quickSort(int[] array) {
if(array.length > 0){
quickSort(array, 0, array.length - 1);
}
}
private static void quickSort(int[] array,int left, int right) {
if(left < right){
int middle = getMiddle(array,left,right);
quickSort(array, left, middle - 1);
quickSort(array, middle + 1, right);
}
}
/**
* 获取新的中轴值,并进行数据交换
* @param array
* @param left
* @param right
* @return
*/
private static int getMiddle(int[] array, int left, int right) {
//记录中轴值
int temp = array[left];
//每一次循环完成左右两个数据的交换,中轴改变
while(left < right){
//循环比较中轴值和右侧数据,直到找到比中轴值小的数据
while(left < right && array[right] >= temp){
//递减,直到找到空位(空位数据将被赋给中轴,左侧较大数据会被赋给空位,中轴数据会被赋给新的中轴(即左侧较大数据位置) )
//右空-中,左大-右空,中-左大,左大变成新中轴
//ps:随便定义一个概念,空位:即复杂赋值过程中值被赋予其它位置的数据所在位置,此时该位置数据已被复制,因此变得可有可无
right--;
}
//比中轴小的移到左侧,即:将比中轴值小的值(空位数据)赋给中轴位置
//右空-中
array[left] = array[right];
//循环比较中轴值和左侧数据,直到找到比中轴大的数据
while(left < right && array[left] <= temp) {
//中轴位置改变
left++;
}
//比中轴大的移到右侧,即:将左侧较大数据赋给右侧空位
//左大-右空
array[right] = array[left];
}
//中轴记录到尾:中轴数据赋给新的中轴
array[left] = temp;
return left;
}
稳定:相同大小的数据在排序后顺序不变
4 归并排序
归并排序是我们常用的八大排序中的一种,其排序思路中和快速排序算法一样使用到了递归的思想,同时在归并排序中还用到了一个算法,就是有序数组合并算法。配合递归与有序数组合并算法,归并排序能够高效且稳定的完成排序,归并排序的优点在于其时间复杂度低,稳定性高,但是缺点也是有的,那就是空间复杂度很高。
参考:java实现8种排序算法