如图所示,先给出排序算法的分类以及性能的比较:
1、冒泡排序
基本思想:
在待排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
冒泡排序的示例:
算法实现:
public void sort(int[] arr){
//参数校验
if(arr == null || arr.length == 0){
return ;
}
//flag表示此时的数组是否是排序好的
boolean flag;
//第一层循环的次数为数组长度-1
for(int i = 0; i < arr.length-1; i++){
flag = true;
//第二层循环的次数为数组长度-1-i
for(int j = 0; j < arr.length-1-i; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = false;
}
}
if(flag == true){
break;
}
}
}
2、简单选择排序
基本思想:
在待排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
简单选择排序的示例:
操作方法:
第一趟,从n 个记录中找出值最小的记录与第一个记录交换;
第二趟,从第二个记录开始的n-1 个记录中再选出值最小的记录与第二个记录交换;
以此类推…
第i 趟,则从第i 个记录开始的n-i+1 个记录中选出值最小的记录与第i 个记录交换,
直到整个序列按值有序
算法实现:
public void sort(int[] arr){
//参数校验
if(arr == null || arr.length == 0){
return ;
}
/**
* 定义最小值和最小值对应的数组下标
*/
int min = 0;
int index = 0;
for(int i = 0; i < arr.length - 1; i++){
min = arr[i];
for(int j = i+1; j < arr.length; j++){
//在遍历过程中,如果该值比最小值还小,就将该值赋给min,然后记录下标
if(min > arr[j]){
min = arr[j];
index = j;
}
}
if(min != arr[i]){
int temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
}
}
3、直接插入排序
基本思想:
将一个记录插入到已排序好的有序表中,从而得到一个新记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
直接插入排序示例:
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
算法实现:
public void sort(int[] arr){
//参数校验
if(arr == null || arr.length == 0){
return ;
}
int sentry = 0; //定义哨兵
for(int i = 1; i < arr.length; i++){
//给哨兵赋值
sentry = arr[i];
for(int j = i -1; j >= 0;j--){
if(arr[j] > sentry){
arr[j+1] = arr[j]; //该值先后移
//避免找到0时,也没有合适的位置插入
if(j == 0){
arr[j] = sentry;
}
}else{
arr[j+1] = sentry;
break;
}
}
}
}