排序方法比较<转>

根据排序的原则,内排序可以分为:

  • 插入排序
  • 交换排序
  • 选择排序
  • 归并排序

预备知识:

1.等差数列之和:S=n*(a1+an)/2

等比数列之和:S=a1(1-q^n)/(1-q)

2.使用哨兵提高效率

比如基本的顺序查找我们可以这样做:

 

 

 

int search(int a[],int n,int key){

    for(int i=0;i<n;i++)

        if(a[i]==key)

            return i+1;         //返回第几个,而不是返回下标

    return 0;                       //返回0说明没有找到

}

注意到每次for循环都对边界进行检查(i<n),使用哨兵就不需要进行边界检查. 

 

 

int search(int a[],int n,int key){

    a[0]=key;

    for(int i=n;a[i]!=key;i--);

    return i;

}

但是使用哨兵的前提是在数组中a[1]--a[n]存储的是实际的元素,a[0]是拿来做哨兵的,a的长度是n+1.

3.time()返回从197011日到现在的秒数,是实际时间。

clock返回开启进程和调用clock()之间的的CPU时钟计时单元(clock tick)数,不包括显式调用sleep()的时间,常用来测试任务执行的速度。

插入排序

简单插入排序

非常的简单,想想你玩牌的时候一边起牌,一边就把牌排好序了,那就是插入排序.

时间复杂度:O(N^2)1+2+...+(N-1)=N^2/2。这是最坏的情况,其实大致上说插入排序的平均情况和最坏情况一样差。

空间上来讲,任一时刻最多只有一个数字在存储数组之外,属于原地排序,O(1)

稳定的排序.

希尔排序

希尔排序利用利用了插入排序的两个特点:

  • 基本有序时直接插入排序最快
  • 对于数据很少的无序数列,直接插入也很快

谢尔排序的时间复杂度在O(nlogn)O(n^2)之间,空间复杂度为O(1).

为了使集合基本有序,而不是局部有序,不能简单地逐段分割,而应将相距为某个增量的元素组成一个子序列.通常取增量为d1=n/2,di+1=di/2.

交换排序

冒泡排序

把待排序的序列分为有序区和无序区,每次把无序区最大的数放到无序区的最后面,这样无序区的末元素成为有序区的首元素.

时间复杂度为O(n^2),空间复杂度O(1).

 快速排序

快速排序是对冒泡排序的改进,由于冒泡排序是不断比较相邻元素然后进行交换,需要比较移动多次才能到达最终位置.而快速排序的比较和移动是从两端向中间进行,因而元素移动的距离较远.

初始主轴的选取采用三元取中法.经过N趟排序,当元素已基本有序后采用直接插入排序法.

 理想情况下,每次划分左右两侧的序列长度是相同的,长度为n的序列可划分为logn.定位一个元素要对整个序列扫描一遍,所需时间为O(n),总的时间复杂度为O(nlogn).

如果每次都取最左边的元素作主轴,最坏情况下待排序列完全有序(正序或逆序),每次划分只得到比上一次少一个的子序列,总的比较次数为1+2+3+...+(n-1)=O(n^2).

平均来说快速排序的时间复杂度为O(nlogn),栈的深度为O(logn).

快速排序是一种不稳定的排序算法.

选择排序

简单选择排序

简单选择排序和冒泡排序很像,每趟排序把把无序序列中最小的元素放到有序列的最后面,有序序列在前,无序序列在后.但有一个重要的区别:冒泡排序在一趟排序中边比较,边交换;而简单选择排序在一趟排序中只作一次交换.

简单选择排序是稳定的,时间复杂度为O(n^2),空间复杂度为O(1).

堆排序

堆排序是对简单选择排序的改进,在简单选择排序中前一次的比较结果没有保存下来,后一趟排序中反复对以前已经做过的比较重新做了一遍.

时间复杂度为O(nlogn),不稳定的排序.

归并排序

二路归并(用内存太多了,不用了。)

 

总结

 

 

 

 

排序方法

平均情况

最好情况

最坏情况

辅助空间

稳定性

直接插入

O(n^2)

O(n)

O(n^2)

O(1)

希尔

O(nlogn)~O(n^2)

O(n^1.3)

O(n^2)

O(1)

冒泡

O(n^2)

O(n)

O(n^2)

O(1)

快速

O(nlogn)

O(nlogn)

O(n^2)

O(nlogn)~O(n)

简单选择

O(n^2)

O(n^2)

O(n^2)

O(1)

堆排序

O(nlogn)

O(nlogn)

O(nlogn)

O(1)

归并

O(nlogn)

O(nlogn)

O(nlogn)

O(n)

:冒泡排序采用pos来标记已有序的序列位置后,最好情况才是O(n),如果没有采用此改进算法,最好情况也是O(n^2).我们的快速排序每次都把主轴放在vec[0],没用另外使用单独的变量,所以辅助空间为O(1),否则就是O(nlogn)~O(n).

http://www.cnblogs.com/zhangchaoyang/articles/1812997.html

你可能感兴趣的:(算法)