选择排序
选择排序:每次在未排序部分选择一个最小的放到前面,并把最小值的标记向后移动一位
特点:
1. 运行时间和输入无关(但是并没有用,因为即使输入时是有序的,仍然会进行遍历与比较,复杂度不变
2. 数据移动量是最少的,因为每次只移动一个元素,移动N次
时间复杂度:最坏n^2,最优n^2平均n^2
缺点:未排序部分若有序,仍会继续遍历
public static void select(int[]arr){
for(int i=0;i<arr.length;i++){
int min = i;//每次假设未排序部分首位为最小值
for(int j=i;j<arr.length;j++){
if(arr[j] < arr[min]){//然后在剩余部分中找出最小值
min = j;
}
}
//将剩余部分的最小值放到i上(即排序部分的末尾)
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
插入排序
插入排序:即把未排序部分的第一个元素拿出来,插入到已排序的部分。将插入位置后面的元素后移。类似于从左往右整理扑克牌
特点:
1. 与选择排序一样,当前索引左边的所有元素都是有序的,但它们的最终位置还不确定,为了给更小的元素腾出空间,它们可能会被移动。但是当索引到达数组的右端时,数组排序就完成了。
2. 数组已经相对有序时,时间会减少很多(整理扑克牌时如果接近有序,也不用花太多时间)
3. 由于插入排序插入时会影响到后续元素的位置,因此用数组来实现会有大量的时间用于元素位置移动。(可以尝试用链表改进)
最坏:n^2 最优 n 平均n^2
public static void insertSort(int arr[]){
for(int i=1;i<arr.length;i++){//插入第i个数
for(int j=i;j>0;j--){ //从第i-1开始往前比较,不停的往前移动
if(arr[j]<arr[j-1]){
int temp = arr[j];
arr[j]=arr[j-1];
arr[j-1] = temp;
}
}
}
}
归并排序
归并排序:采用分治思想,将一个数组的排序转化为若干小数组的排序,然后将结果归并起来
采用分治思想算法复杂度始终是nlogn
public static void merge(int arr[]){
mergeSort(0,arr.length-1,arr);
}
public static void mergeSort(int lo,int hi,int arr[]){
if(lo>=hi) return;
int mid = lo + (hi-lo)/2;
mergeSort(lo,mid,arr);
mergeSort(mid+1,hi,arr);
merge(lo,mid,hi,arr);
}
public static void merge(int lo,int mid,int hi,int[] arr){
int[] temp = new int[arr.length];
for(int i=lo;i<=hi;i++){
temp[i] = arr[i];
}
int j = mid+1;
int k = lo;
int f = lo;
while(f <= hi){
if(k > mid) arr[f++] = temp[j++];
else if(j > hi) arr[f++] = temp[k++];
else if(temp[k] < temp[j]) arr[f++] = temp[k++];
else arr[f++] = temp[j++];
}
}
快速排序
快速排序:快速排序也是采用分治思想的排序,快速排序的思路是选取一个随机元素一般是a[lo](待排部分首位),
然后在分别从lo->hi,hi->lo进行扫描,从左边元素找到一个比a[lo]大的,在右侧找到一个比a[lo]小的,进行位置交换,直到左右扫描的标记相遇
如果i>=j ,说明 i 左侧元素一定比a[lo]小了,并且j右侧元素一定比a[lo]大了此时把a[lo]放到a[i]与a[j]之间即可
顺序或逆序的数组进行快排的性能十分之低,所以在进行操作之前应该先对其进行一个打乱操作(此处未打乱)
public static void quick(int []arr){
quickSort(0,arr.length-1,arr);
}
public static void quickSort(int lo,int hi,int[] arr){
if(lo>=hi) return;
int a = partion(lo,hi,arr);
quickSort(lo,a-1,arr);
quickSort(a+1,hi,arr);
}
public static int partion(int lo,int hi,int[]arr){
int i=lo+1;
int j=hi;
int part=arr[lo];
while(i<=j){
while(arr[i]<part){
if(i==hi) break;
i++;
}
while(arr[j]>part){
if(i==lo) break;
j--;
}
if(i>=j) break;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
arr[lo] = arr[j];
arr[j] = part;
return j;
}