数据结构—排序III

一.            归并排序

 

【基本思想】 将两个或两个以上的有序表合成一个新的有序表。

 

归并-算法步骤】设有两段有序表A[ low …mid]  A[mid+1…high] 存放在同一顺序表的相邻位置上,现将他们复制到辅助数组B中(这里是关键,决定了无论何种情况,即和输入状态无关,该算法空间复杂度为O(n))。每次从对应B中两个段取出一个记录进行关键字比较,将较小者放入A中,当数组B中有一段(逻辑上分为两段嘛)的下标超出其对应长度时(即该段的所有元素已经完全复制到A中,见代码),将另一段中剩余部分直接复制到A中。

归并代码】

ElemType*B=(ElemType*)malloc((n+1)*sizeof(ElemType)); //辅助数组

Void Merge(ElemTypeA[],int low,int high)

{

       For( k=low;k<=high;k++)

              B[k]=A[k];

       For(i=low;j=mid+1;k=i;i<=mid&&j<=high;k++)  //注意k起点是i

       {

              If(B[i]<=B[j])                           

                     A[k]=B[i++];             //对暂存表B扫描比较,再写回原表A

              Else

                     A[k]=B[j++];

       }

       While(i<=mid)   A[k++]=B[i++]; //第一个表未检测完

While(j<=high)  A[K++]=B[j++]; //【注】只会执行一个

}





【2路归并排序-递归形式】

 

1.        分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用2路归并排序算法对两个子表递归的进行的排序。  【分治的思想,太巧妙了】

2.        合并:合并两个已排序的子表得到排序结果

 

【代码】

VoidmergeSort(ElemType A[],int low,int high)

{

If(low<high)      //只能low<high,如果low=high说明定位到一个元素了,无法归并

{

         Int mid=(low+high)/2;

         MergeSort(A,low,mid);             //注意mid, 归并要保证所有元素都取到

         MergeSort(A,mid+1,high);

         Merge(A,low,mid,high);                     //处理完了子序表,就是归并了

}

}





【2路归并排序-递归形式】

 

1.        分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用2路归并排序算法对两个子表递归的进行的排序。  【分治的思想,太巧妙了】

2.        合并:合并两个已排序的子表得到排序结果

 

【代码】

VoidmergeSort(ElemType A[],int low,int high)

{

If(low<high)      //只能low<high,如果low=high说明定位到一个元素了,无法归并

{

         Int mid=(low+high)/2;

         MergeSort(A,low,mid);             //注意mid, 归并要保证所有元素都取到

         MergeSort(A,mid+1,high);

         Merge(A,low,mid,high);                     //处理完了子序表,就是归并了

}

}







二.            基数排序

 

【思想】不是基于比较进行排序,而是采用多关键字排序思想(即基于关键字各位的大小进行排序的),借助”分配“和“收集”两种操作对单逻辑关键字进行排序。分为最高位有先(MSD)和最低位优先(LSD=Least significant digit)排序

 








【性能分析】

空间效率:一趟排序需要辅助存储空间为2r(分别是r个队头和队尾指针,r是基数),但以后的排序中重复使用这些队列,所以基数排序的空间复杂度为O(2r)

 

时间效率:基数排序需要进行d(表示位数)趟分配和收集,一趟分配需要O(n)(扫描表并逐个分配到对应的队列中去,),一趟收集需要O(r)(扫描r个队列,修改一次非空队列的尾指针即可),所以基数排序时间复杂度为O(d(n+r)),它与序列的初始状态无关





各算法的比较

1.        时间复杂度:

1)        简单选择排序,直接插入排序和冒泡排序的平均时间复杂度都为O( ,并且实现过程也比较简单, 直接插入排序和冒泡排序最好情况下时间复杂度可达到O(n),而简单选择排序则与序列的初始状态无关。

2)        希尔排序作为插入排序的拓展,对较大规模的排序都可达到很高效率,但是目前未得出其精确的渐进时间。 

3)        堆排序是利用一种称为堆的数据结构,可以在线性时间内完成建堆,并且在O( ) 内完成排序过程。    

4)        快速排序是基于分治思想,虽然最坏情况下时间复杂度达到O( ,但其平均性能可以达到O( ),在实际应用中常常优于其他算法。       

5)        归并排序同样是基于分治思想,但由于其分割子序列和初始状态排列无关,因此它的最好,最坏和平均时间复杂度都为O( )




1.        空间复杂度:

1)        简单选择排序,插入排序,冒泡排序,希尔排序和堆排序都仅需要借助常数个辅助空间。

2)        快速排序在空间上只使用一个小的辅助栈,用于实现递归,平均情况下为O( )(因为最坏情况为O(n))。

3)        二路归并排序在合并操作中需要借助O(n)辅助空间用于元素复制,虽然有其方法可以克服这个缺点,但是代价是算法复杂和时间复杂度增加。

        

2.        稳定性:        插入排序,冒泡排序,归并排序和基数排序都是稳定的排序方法,而简单选择排序,快速排序,希尔排序和堆排序都是不稳定的排序方法。(原因在于这些有跨区间交换

 

3.        过程特征:  

1)        冒泡排序和堆排序每次循环后都能产生当前最大值或者最小值,

2)        快速排序一次循环就确定一个元素的最终位置。

 

 

排序算法小结

1.        若n较小(n<=50),则可以采用直接插入排序或简单选择排序。由于直接插入排序所需记录移动操作较简单选择排序多,因而当记录本身信息量较大时,用简单选择排序好。    

2.        若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜(最好情况可以为O(n)

 

3.        若n较大,则应采用时间复杂度为O( )的排序方法:快速排序,堆排序或归并排序。 快速排序被认为是目前基本比较的内部排序法中最好的方法。

 

4.        在基于比较的排序算法中,每次比较两个关键字大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定的过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于“比较”的排序算法,至少需要O( )(n次判定,每次至少需要)

 

5.        当记录本身信息量很大时,为避免耗费大量时间移动记录,可用链表作为存储结构。

 




一.            外部排序

 

【引】大文件进行排序时,由于无法将整个文件拷贝进内存中进行排序。因此,需将待排序的记录存储在外存上,排序时再把数据一部分一部分的调入内存进行排序。在排序过程中需要多次进行内外存之间的交换,对外存文件中的记录进行排序后仍然被放到原有文件中。

这种排序方法称之为外部排序。

 

【定义】由两个相对独立的阶段组成。

1.        按可用内存大小,将外存上含n个记录的文件分成若干长度为l的子文件或段(segment),依次读入内存并利用有效的内部排序方法对它们进行排序,并将排序后得到了有序子文件重新写回外存,通常称这些有序子文件为归并段或顺串(run)

对这些归并段进行逐趟归并,使归并段(有序的子文件)逐渐由小到大,直至得到整个







并将l个归并段归并成⌈l/m⌉个归并段,直到最后形成一个大的归并段为止。树的高度=⌈⌉=归并趟数S可见,

增大归并路数,或者减少初始归并段个数,都能减少归并趟数S,以减少读写磁盘次数d,达到提高外部排序速度的目的。


 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值