直接插入排序:
直接插入排序通过线性搜索来确定待排序记录的位置,在待排序记录的前面形成一个单调的序列,对已排序记录按照从大到小依次逐个进行比较。直到找到适合的位置(具体情况根据增减)。时间效率为O(n^2),空间效率为O(1),最好时间代价为O(n),最差时间代价为O(n^2)。直接插入排序对于基本有序的短序列排序的效率比较高,所以,之后几种算法的优化都可以利用直接插入排序这一特性。
- void insertSort(int a[], int n){
- int i,j,tmp;
- if(n <= 1){return ;}
- for(i=1 ; i<n ; i++){
- tmp = a[i];
- j = i-1;
- while(j >= 0 && a[j] > tmp){
- a[j+1] = a[j];
- j--;
- }
- a[j+1] = tmp;
- }
- }
希尔排序:
先将序列分成若干子序列,而且要保证子序列中的记录在原始的数组中不相邻,而且间距相同,分别对这些小队列进行排序。,然后减少记录间距,减少子序列个数,将原始序列分成更大、更有序的序列,进行插入排序,直到最后间距为一。希尔排序实质上是对于直接插入排序效率的一种折中,直接插入排序的适用短而基本有序的序列。希尔排序在排序的不同时期分别利用到了直接插入排序的优点。前期主要是采用排序短的序列,后期排列基本有序的长序列,可以说希尔排序,就是利用直接插入排序的优点,有针对性地对序列进行优化。时间复杂度:O(n^3/2)(跟序列的状态无关),空间复杂度O(1)。还有这种排序是不稳定的,因为他不是通过比较相邻记录实现插入的排序。
- void shellSort(int a[], int n){
- int i,delta;
- for(delta=n/2; delta > 0; delta /= 2){
- for(i = 0; i<delta; i++){
- insertModSort(&a[i],n-i,delta);
- }
- }
- insertModSort(a,n,1);
- }
- void insertModSort(int a[],int n,int delta){
- int i,j,tmp;
- for(i=delta; i<n ; i+=delta){
- tmp = a[i];
- j = i - delta;
- while(j>=0 && a[j] > tmp){
- a[j+delta] = a[j];
- j -= delta;
- }
- a[j+delta] = tmp;
- }
- }
直接选择排序:
选择排序的原理很简单,就是扫描整个数组,找出最大值或最小值,然后把这个值与最前的记录交换。接着从第二个记录开始,扫描一遍数组,找出最大或最小值与第二个记录交换,如此反复,知道最后一个记录为止,整个数组有序。时间代价与记录的初始排列无关为O(n^2),空间代价为O(1)。直接选择排序,每一趟排序都是直接从线性剩余记录中查找最大记录,没有利用到之前的结果,故而效率较低。
- void selectSort(int a[], int n){
- int i,j,s,tmp;
- if(n <= 1)
- return;
- for(i=0; i<n; i++){
- s = i;
- for(j = i+1; j<n ; j++ ){
- if(a[s]>a[j]){
- s = j;
- }
- }
- tmp = a[i];
- a[i] = a[s];
- a[s] = tmp;
- }
- }
堆排序:
堆排序也是一种基于选择的排序。它是采用一种树形堆结构来储存剩余记录,而树形的堆结构的调整花费的时间是O(log(n)),因而比较高效。时间代价为O(n*log(n)),空间代价刚好为:O(1),排序主要分成两步:
1.对所有记录建最大堆,具体参照建堆的思路。
2.取出堆顶最大记录与数组末端的数进行交换,然后调整堆,如此往复,直到堆建好为止。
冒泡排序:
这是一种基于交换的排序,通过不停的比较相邻记录,然后实现基本有序。时间代价:O(n^2),空间代价:O(1)。
- void bubbleSort(int a[] , int n){
- int i,j,tmp;
- bool isSort = true;
- for(i=0;i<n;i++){
- for(j=n-1;j>i;j--){
- if(a[j-1] > a[j]){
- tmp = a[j];
- a[j] = a[j-1];
- a[j-1] = tmp;
- isSort = false;
- }
- }
- if( true ==isSort){
- break;
- }
- }
- }
快速排序:
这是我最喜爱的一种排序方法,快排对于随机状态的排序效率最高。这个一种基于分治法的排序算法,关键在于分、治、合,最终合并成一个可行解,时间效率为O(n*log(n)),空间效率为:O(log(n))。快排是一个不稳定的排序算法算法步骤如下:
1.从带排记录中选出一个记录作为轴值;
2.将剩余记录分割成左子序列L和右子序列R;
3.L中的所有记录都小于轴值,R中的记录都大于等于轴值;
4.对子序列L、R进行递归调用,直到子序列中只含有0或1个记录的序列,退出递归调用。
- void quickSort(int a[], int l, int r){
- if(l >= r)
- return;
- int left = l,right = r;
- int pivot = a[l];
- while(true){
- while(l<r && a[r]>=pivot)
- r--;
- if(l<r){
- a[l] = a[r];
- l++;
- }
- while(l<r && a[l]<=pivot)
- l++;
- if(l<r){
- a[r] = a[l];
- r--;
- }
- if(l == r){
- a[l] = pivot;
- break;
- }
- }
- quickSort(a,left,l-1);
- quickSort(a,l+1,right);
- }
归并排序:
这也是一种采用分治法的排序方法,它将原始序列划分成两个子序列,然后分别对子序列递归,最后将子序列合并,一个典型的分,治,合的思想。时间代价为O(n*log(n)),空间代价为O(n)。需要一个额外的临时数组,与快排不同,归并排序是一种稳定的排序。思路如下:
1.将原始序列分成两个子序列;
2.分别对两个子序列进行递归进行归并排序;
3.将这两个已经排好的子序列归并到一个数组里;
桶排序:
桶排序是完全不同于之前排序算法,他是基于收集的分配排序函数。因而他的时间代价可以达到O(m+n),空间代价为O(m+n),m为排序值的区间长度,因而是一个十分高效的排序算法,但是它的适用的范围有限,它适用于区间跨度较小(m的值较小)的待排序列。
基数排序:
基数排序是基于桶排序的,我们可以认为他是针对桶排序的一种优化,它将排序码拆分成多个部分进行比较。如果要对0~9999之间的整数进行排序,那么只需要将数字拆成个、十、百、千,分别对这四个进行桶排序,当然我们得采用低位优先法,方便我们的程序实现。时间代价为O(d*(n+r)),空间代价为O(n+r)。
转载于:https://blog.51cto.com/webcrawler/1193754