现在的位置: 首页 > 综合 > 正文

排序详解

2014年02月13日 ⁄ 综合 ⁄ 共 3000字 ⁄ 字号 评论关闭

排序是数据处理中经常使用的一种重要运算,在计算机及其应用系统中,花费在排序上的时间在系统运行时间中占有很大比重;并且排序本身对推动算法分析的发展也起很大作用。目前已有上百种排序方法,但尚未有一个最理想的尽如人意的方法,本章介绍常用的如下排序方法,并对它们进行分析和比较。


1、插入排序(直接插入排序、折半插入排序、希尔排序);

2、交换排序(起泡排序、快速排序);

3、选择排序(直接选择排序、堆排序);

4、归并排序;

5、基数排序;

我们所练习的排序主要是内部排序,所谓内部排序,就是整个排序过程都在内存进行的排序,称为内部排序;反之,若排序过程中要进行数据的内、外存交换,则称之为外部排序。内排序适用于记录个数不是很多的小文件,而外排序则适用于记录个数太多,不能一次性放人内存的大文件。

   对排序算法的分析可以从以下几个方面进行:排序算法的稳定性、平均时间、最坏情况、辅助存储空间。

   从稳定性来说,稳定的排序算法有:直接插入排序、冒泡排序、归并排序,其它排序算法都是不稳定的。

                               平均时间           最好情况          最坏情况        辅助空间

   直接插入排序            O(n*n)            O(n)                O(n*n)          O(1)

   希尔排序排序            O(n1+£)          O(n)                O(n*n)          O(1)   

                        £是介于0和1之间的常数

   冒泡排序                  O(n*n)            O(n)                O(n*n)          O(1)   

   快速排序                  O(nlogn)          O(nlogn)          O(n*n)         O(nlogn)

   直接选择排序             O(n*n)            O(n*n)            O(n*n)          O(1)

   堆排序                     O(nlogn)          O(nlogn)          O(nlogn)       O(1)

   归并排序                  O(nlogn)          O(nlogn)          O(nlogn)       O(1)

                  

各种排序方法比较

     简单排序中直接插入最好(稳定、易于实现),快速排序最快,当文件为正序时,直接插入和冒泡均最佳。

   
(1)若n较小(如n≤50),可采用直接插入或直接选择排序。

当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。

    (2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;

    (3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。

快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。若要求排序稳定,则可选用归并排序。但本章介绍的从单个记录起进行两两归并的排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。

排序(sort)或分类


     所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。其确切定义如下:

  输入:n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn

  输出:Ril,Ri2,…,Rin,使得Ki1≤Ki2≤…≤Kin。(或Ki1≥Ki2≥…≥Kin)。

1.被排序对象--文件

  被排序的对象--文件由一组记录组成。

  记录则由若干个数据项(或域)组成。其中有一项可用来标识一个记录,称为关键字项。该数据项的值称为关键字(Key)。

  注意:

     在不易产生混淆时,将关键字项简称为关键字。

2.排序运算的依据--关键字

     用来作排序运算依据的关键字,可以是数字类型,也可以是字符类型。

     关键字的选取应根据问题的要求而定。

【例】在高考成绩统计中将每个考生作为一个记录。每条记录包含准考证号、姓名、各科的分数和总分数等项内容。若要惟一地标识一个考生的记录,则必须用"准考证号"作为关键字。若要按照考生的总分数排名次,则需用"总分数"作为关键字


排序的稳定性

    
当待排序记录的关键字均不相同时,排序结果是惟一的,否则排序结果不唯一。

   
 在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是
稳定的;若具有相同关键字的记录之间的相对次序发生变化,则称这种排序方法是不稳定的
  注意:
    
排序算法的稳定性是针对所有输入实例而言的。即在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该排序算法就是不稳定的

稳定意思是说原本键值一样的元素排序后相对位置不变

  学习的时候,可能编的程序里面要排序的元素都是简单类型,实际上真正使用的时候,可能是对一个复杂类型的数组排序,而排序的键实际上只是这个元素中的一个属性,对于一个简单类型,数字值就是其全部意义,即使交换了也看不出什么不同。。。但是对于复杂的类型,交换的话可能就会使原本不应该交换的元素交换了。
比如,一个“学生”数组,按照年龄排序,“学生”这个对象不仅含有“年龄”,还有其他很多属性,稳定的排序会保证比较时,如果两个学生年龄相同,一定不交换。

判断方法

  对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。
  例如,对于如下起泡排序算法,原本是稳定的排序算法,如果将记录交换的条件改成r[j]>=r[j+1],则两个相等的记录就会交换位置,从而变成不稳定的算法。
  void BubbleSort(int r[ ], int n){
  exchange=n; //第一趟起泡排序的范围是r[1]到r[n]
  while (exchange) //仅当上一趟排序有记录交换才进行本趟排序
  {
  bound=exchange; exchange=0;
  for (j=1; j if (r[j]>r[j+1]) {
  r[j]←→r[j+1];
  exchange=j; //记录每一次发生记录交换的位置
  }
  }
  }
  再如,快速排序原本是不稳定的排序方法,但若待排序记录中只有一组具有相同关键码的记录,而选择的轴值恰好是这组相同关键码中的一个,此时的快速排序就是稳定的

抱歉!评论已关闭.