常见排序算法——七大比较类排序算法
2018-07-07 11:30 bluemapleman 阅读(816) 评论(0) 编辑 收藏 举报|算法|最坏复杂度|平均复杂度|最好复杂度|空间复杂度|稳定性|
|--|--|--|--|--|
|选择排序|O($n2$)|O($n2$)|O($n^2$)|O(1)|不稳定|
|插入排序|O($n2$)|O($n2$)|O($n$)|O(1)|稳定|
|希尔排序|O($nlog(n))$~O($n2$)|O($n$)|O($n^2$)|O(1)|不稳定|
|冒泡排序|O($n2$)|O($n2$)|O(n)(用交换flag改进)|O(1)|稳定|
|快速排序|O($n^2$)|O($nlog(n)$)|O($nlog(n)$)|O(log(n))~O(n)|不稳定|
|堆排序|O($nlog(n)$)|O($nlog(n)$)|O($nlog(n)$)|O(1)|不稳定|
|归并排序|O($nlog(n)$)|O($nlog(n)$)|O($nlog(n)$)|O(n)|稳定|
Java实现
选择排序
//选择排序:每次遍历找到数组中的最小值,放到剩余数组最前面,以此类推,直到所有元素被排好
public static void select_sort(int[] arr){
int len=arr.length;
long start=System.currentTimeMillis();
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
if(arr[i]>arr[j]){
swap(arr,i,j);
}
}
}
long end=System.currentTimeMillis();
System.out.println("选择排序耗时(秒):"+(end-start));
//toPrint(arr);
}
插入排序
//插入排序:用新的元素去与已经排序好的元素数组从尾部开始比较,若比对应元素小,则下标继续往前走,直到找到比新元素小的元素,然后将比新元素小的元素后面的全部元素后移,插入新元素。
public static int[] insert_sort(int[] arr){
long start=System.currentTimeMillis();
for(int i=0;i<arr.length;i++){
int temp=arr[i];
for(int j=i;j>0 && arr[j-1]>arr[j];j--){
arr[j]=arr[j-1];
arr[j-1]=temp;
}
}
long end=System.currentTimeMillis();
System.out.println("插入排序耗时(秒):"+(end-start));
return arr;
//toPrint(temparr);
}
希尔排序
//希尔排序:以arr.length/2为开始间隔,并不断/2缩小间隔的插入排序,最后一次的循环比较e就是插入排序,但是数组的绝大部分元素已经处于相对有序状态。
public static int[] shell_sort(int arr[]){
for(int gap=arr.length; gap>0 ; gap/=2){
for(int i=gap;i<arr.length;i++){
int temp=arr[i];
for(int j=i;j>=gap && arr[j-gap]>arr[j];j-=gap){
arr[j]=arr[j-gap];
arr[j-gap]=temp;
}
}
}
return arr;
}
冒泡排序
//冒泡排序:比较相邻两个元素的大小,决定是否交换位置,每次循环可将一个最大值元素一直交换到最后面(或者将最小值一直交换到最前面),以此类推。用一个交换flag作优化可以将最优情况时间复杂度降到O(n),即只比较一轮。
public static void bubble_sort(int[] arr){
int len=arr.length;
long start=System.currentTimeMillis();
boolean swapFlag=true;
for(int i=0;i<len;i++){
if(swapFlag==false)
break;
swapFlag=false;
for(int j=1;j<len-i;j++){
if(arr[j-1]>arr[j]){
swap(arr,j-1,j);
swapFlag=true;
}
}
}
快速排序
//思路:每一次排序,将首元素(arr[0])交换到这样的位置,即它所在位置往右的所有元素都不小于它,且它所在位置往左的所有元素都不大于它。完成这一步,只需要将首元素不断地从右往左遍历找比它小的,然后从左往右找比它大的,找到即交换位置,一直到从两个方向都再也找不到一个可以交换的元素,一轮排序结束。接着用递归的方式排序剩下的两半。
public static void quickSort(int[] arr,int start,int end){
if(start>=end)
return;
boolean leftFlag=false,rightFlag=false;
int pivot=start;
System.out.println("hehe");
while(!(leftFlag && rightFlag)){
leftFlag=true;rightFlag=true;
//第一轮:第一个元素从右边开始找第一个比它小的元素,与之交换位置
for(int i=end;i>=start;i--){
if(arr[pivot]<arr[i]){
exchange(arr, pivot, i);
pivot=i;
leftFlag=false;
}
}
System.out.println("循环");
for(int i=start;i<=end;i++){
if(arr[pivot]<arr[i]){
exchange(arr, pivot, i);
pivot=i;
rightFlag=false;
}
}
}
quickSort(arr, start, pivot-1);
quickSort(arr, pivot+1,end);
}
堆排序
归并排序
//思路:将数组不断划分为更小的两个数组的组合(递归),当划分到最小的粒度时,即两个数之间的比较与位置交换,然后不断将两个小的数组融合成大的数组(merge方法)。
public static void merge_sort(int[] arr,int low,int high){
if(high>low){
int pivot=(high+low)/2;
merge_sort(arr,low,pivot);
merge_sort(arr,pivot+1,high);
merge(arr,low,pivot,high);
}
}
private static void merge(int[] arr,int low,int pivot,int high){
int[] temp=new int[high-low+1];
int i=low,j=pivot+1;
int count=0;
while(i<=pivot && j<=high){
if(arr[i]>arr[j]){
temp[count++]=arr[j];
j++;
}
else{
temp[count++]=arr[i];
i++;
}
}
while(i<=pivot){
temp[count++]=arr[i];
i++;
}
while(j<=high){
temp[count++]=arr[j];
j++;
}
for(int x=0;x<temp.length;x++){
arr[low+x]=temp[x];
}
}
知识太多,我只想活到老,学到老~