排序:元素数组的排序问题
- 内部排序:在主存中完成
- 外部排序:在磁盘或磁带中完成
排序的稳定性
当待排序记录的关键字均不同时,排序结果是唯一的,否则排序结果是不唯一的。
若存在多个关键字相同的记录,经过排序后,这些具有相同关键字的记录之间的相对次序保持不变,该排序算法稳定。否则不稳定。
排序算法汇总表:
排序算法的基本操作:
- 比较2个关键字的大小
- 改变指向记录的指针或移动记录本身
待排文件的常用存储方式:
- 顺序表:排序过程是对记录本身进行物理重排
- 链表:排序过程无需移动记录,仅需改变指针
- 顺序存储,同时建立辅助表(关键字和指向记录位置的指针组成的索引表):排序过程只需要对辅助表的表目仅需物理重排
基于比较的排序
1- 插入排序(冒泡,选择)
由N-1趟排序组成,对P=1到N-1趟,插入排序保证0到位置P上的元素为已排序状态【即已知位置0到P-1上的元素已经处于排过序的状态】
PS:实现复杂度N的平方(嵌套循环),如果数据已经预先有序,运行时间为N,内层循环不执行。
基于交换排序的2个定理:
- 通过交换相邻元素进行排序的任何算法平均都要N的平方的时间
- N个互异数的数组的平均逆序数为N(N-1)/4
插入排序的详细介绍:http://blog.csdn.net/wee_mita/article/details/71055861
2- 希尔排序(缩减增量排序)
使用一个序列h1,h2,…,ht叫做增了序列,只要h1=1,任何增量序列都可行。在使用增了hk的一趟排序后,对于每一个i都有a[i]<=a[i+hk],即所有的相隔hk的元素都被排序
增量的流行选择(但并不是做好的)是:ht=N/2向下取整和hk=hk+1/2向下取整
- 使用希尔增量时,希尔排序的最坏运行时间为N的平方
- 使用Hibbard增量时,希尔排序的最坏运行时间N的3/2次方
希尔排序的详细介绍:http://blog.csdn.net/wee_mita/article/details/71056129
3- 堆排序
基于二叉堆(优先队列)的排序
【使用一个附加数组存放从根出发的元素,因此存储空间要增加一倍】—>优化策略:从根出来一个元素,堆就减小1,减小的位置用来存放出来的元素,空间消耗不变。
对于N个互异项的随机排列进行堆排序所用比较平均次数为2NlogN-NloglogN
4 - 归并排序(分治的递归算法)
基本操作是合并两个已排序的表【数组A&数组B—>数组C】
A[Actr]&B[Bctr]中较小的拷贝到C中,相关计数器向前推进,当A&B中有一个用完,另一个剩下的全部加入C中
合并两个已排序表的时间是线性的,最多N-1次比较,N为元素个数
操作流程:
- 递归的将钱半部分和后半部分各自归并排序
- 用上面的基本操作得到排序后数据
占用空间大:用到一个临时数组——>优化策略:非递归实现
归并排序的运行时间严重依赖于比较元素和在数组中移动元素的相对开销(这些开销和语言有关)
归并排序的详细介绍:http://blog.csdn.net/Wee_Mita/article/details/71056672
5- 快速排序
是实践中的一种快速排序算法(分治的递归算法)
最常用的快速排序:其输入存放在数组中且算法不产生额外的数组
将数组S排序的基本步骤:
- 如果S中算是个数为0或1,则直接返回
- 取S中任一元素U【(left+right)/2】,称为枢纽元
- 将S-{U}(S中其他元素)分为两个不想交的集合,S1={X属于S-{U}|X<=U},S2={X属于S-{U}|X>=U}
- 返回{quicksort(S1)+U+quicksort(S2)}
快速排序的详细介绍:http://blog.csdn.net/Wee_Mita/article/details/71056786
线性时间排序
6- 桶排序
输入数据A1,A2,…,AN必须仅由小于M的正整数组成,如果这种情况,使用一个大小为M的count数组,初始化为0。count有M个桶,当读入Ai时候,count[Ai]增加1。所有数据被读入后,扫描count,打印出排序后的表
7- 基数排序(卡片排序):
按位数排,第一次个位,第二次十位,依次,第K趟元素按第K位有序(唯一可能的失败会发生在两个数从同一个桶出来的时候,出错顺序了),排序完成