排序算法总结

来源:互联网 发布:淘宝店铺导航css模板 编辑:程序博客网 时间:2024/04/30 06:43

最近在刷leetcode,被虐n次之后决定先搞一下基础建设,把排序整理一下。差不多两天的时间(主要是快速排序把我搞到头大),终于出了一篇比较简陋的笔记。暂且看着,留着后面用。

***华丽的分割线,下面是笔记***

各类排序算法总结

交换排序,选择排序,插入排序,合并排序

基本排序(直接对内存中的 数据进行排序)

交换排序

选择排序

插入排序

合并排序

冒泡排序

快速排序

选择排序

堆排序

插入排序

Shell排序

       

 

若对于一些大的 文件,采用 多路归并排序。将文件分为几个能读入内存的小部分,然后分别读入进行排序。

*** 分隔线*** 

冒泡排序

比较简单,原理这里不写了就。复杂度:average和worst都是O(n2)。

选择排序

进行n-1次循环,每次循环都找出剩余数组里最小的一个,然后跟当前元素互换。

                复杂度:average和worst都是O(n2)。

                代码:

public void selectSort(int[] arr){for(int i=0;i<arr.length;i++){int k = i;for(int j=i+1;i<arr.length;j++){if(arr[j]<arr[k]) k=j;}if(k!=i){int temp = arr[k];arr[k] = arr[i];arr[i] = temp;}}}

插入排序

                思想流程:

                1)先把前两个数据排好序。

                2)将第三个数据插入到前面排好序的数组里。

                3)以此类推。

                思想很简单,就是把后面紧挨的数往前扫,如果被扫的数比这个数大,就存到后面去,直到发现一个比这个数小的就停止。

                说的不清楚。。。上代码:

public static void insertSort(int[] a){int len = a.length;for(int i=1;i<len;i++){int temp = a[i];int j=i-1;for(;j>=0;j--){if(a[j]>=temp){a[j+1] = a[j];}else{break;}}a[j+1] = temp;}}

               

Shell排序:虽然不知道为什么叫Shell排序。。。

根据Shell排序的思想,自己写的代码跟书上的不太一样。

                排序流程如下:

                1) 将n个元素的数组分成n/2个数字序列,比如8个数字除以2是4个数字序列,然后第一个数据和第n/2+1个数据为一对。。。

                2)依次循环是每一个序列对排好顺序。

                3)然后再变为n/4个序列,再次排序。这里我没太懂,我的代码理解是以n/4为间隔划分整个数组,然后依次比较每一对组合的大小,小的放前面,大的 放后面。书中用的是插入排序,好混乱不懂==

                4)不断重复上述过程,直到序列减少为最后一个。我的理解是序列间隔最后变为1,这样每相邻两个数字都是有序的 ,所以整个数组就是有序的了。

                上代码:注释部分是书上的代码。

               

public static void shellSort(int[] arr){int len = arr.length;//for(int r = len/2;r>=1;r/=2)//{//for(int i=r;i<len;i++)//{//int temp = arr[i];//int j=i-r; //mark the other element of a pair//while(j>=0 && temp<arr[j])//{//arr[j+r] = arr[j];//j-=r;//}//arr[j+r]=temp;//}//}for(int r = len/2;r>=1;r/=2){for(int i=0;i<len-r;i++){if(arr[i]>arr[i+r]){int temp = arr[i];arr[i] = arr[i+r];arr[i+r] = temp;}}}}

QuickSort快速排序

                思路:找一个基准元素,随便哪个都可以,然后把比它小的数字都排到左边,比它大的数字都排到右边。然后递归。快速排序可以被形容为:挖坑填数+分治法。

                先上代码:

               

public static void quickSort(int[] arr, int left, int right){if(left < right){int i = left;int j = right;int base = arr[left];while(i<j){while(arr[j]>=base && i<j)j--;if(i<j){arr[i++] = arr[j];}while(arr[i]<base && i<j)i++;if(i<j){arr[j--] = arr[i];}}arr[i] = base;quickSort(arr,left,i-1);quickSort(arr,i+1,right);}}

While是为了挖坑填数,填好一层后用递归分治。

                几点注意:在内层有个if判断,它的用途是为了防止如果j从后往前找没找到比arr[i]小 的数,这个时候就不用填数然后移动i了,否则在大while结束后给arr[i]赋值时会赋错位置。

 

归并排序

                思路:把数组分成两个部分排序,排好之后再把两个部分合起来。如果被分的 两个部分还可以继续分,则分至最小后排序,然后合并。

                上代码:

public static void mergeSort(int[] arr,int first, int last){if(first>=last)return;int mid = (first+last)/2;mergeSort(arr,first,mid);mergeSort(arr,mid+1,last);mergeArray(arr,first,mid,last);}public static void mergeArray(int[] arr, int first, int mid, int last){int i = first;int j = mid+1;int[] temp = new int[last-first+1];int k = 0;while(i<=mid && j<=last){temp[k++] = arr[i]<arr[j]? arr[i++]:arr[j++];}while(i<=mid){temp[k++] = arr[i++];}while(j<=last){temp[k++] = arr[j++];}for(int m=0;m<temp.length;m++)arr[first+m] = temp[m];}

               

mergeArray负责把排好序的两个部分合并成一个部分,然后返回到上一级mergeSort继续合并。

关键点:在整个数组中,分组是靠下标实现的。

 

总结

归并排序的空间复杂度为O(n),其余都大部分都是O(1)。

时间复杂度总结:

 

Average

Worst

Bubble Sort

N2

N2

Select Sort

N2

N2

Insert Sort

N2

N2

Quick Sort

nlogn

N2

Shell Sort

N3/2

N2

Merge Sort

nlogn

Nlogn

 

由此可以看出,mergesort是效率较高的,尤其是当排序的数量较多时,但需要额外的系统资源。

***华丽的分割线结束***


码字不易,大神勿喷,欢迎指正。

1 0