数据结构——常见的十种排序算法

Posted blancheiii

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——常见的十种排序算法相关的知识,希望对你有一定的参考价值。

一、常见的十种排序算法:
  冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、桶排序、基数排序
1.【知识框架】
 
技术分享图片
补充:内部排序:整个排序过程完全在内存中进行。
            外部排序:由于待排序记录数据量太大,内存无法容纳全部数据,需要借助外部存储。
 
二、排序方法
 
?插入排序
1.算法思想
   从待排序的第二个元素开始,向下扫描列表,比较这个目标值target与arr[i-1]、arr[i-2]的大小,依次类推。如果target的值小于或等于每一个元素值,那么每个元素都会向右滑动一个位置,一旦确定了正确位置j,目标值target(即原始的arr[i])就会被复制到这个位置。(例如:整理桥牌时,我们会将每一张牌插入到一个已经有序的序列的适当位置。为了给要插入的元素腾出空间,需要我们将已经有序的序列元素都向右移动一位)
2.算法实现

 
技术分享图片

3.插入排序伪代码

 1 void InsertSort (ElemType A[], int n)
 2 {
 3    int i,j;
 4    for(i=2;i<=n;i++)
 5         if(A[i].key<A[i-1].key)
 6     {
 7         A[0]=A[i];
 8         for(j=i-1;A[0].key<A[j].key;--j)
 9                 A[j+i]=A[j];
10         A[j+i]=A[0];
11     }
12 }

4.稳定性

  由于每次插入元素时总是从后往前先比较在移动,所以不会出现相同元素相对位置,发生变化的情况即直接插入排序是一个稳定的排序方法

5.时间复杂度:O(n2

 

 ?希尔排序(缩小增量排序)

1.算法提出:

 为解决插入排序每次只能将数据移动一位,在数组较大且基本无序的情况下性能出现的恶化所以引入其算法。
2.算法思想: 
 先取一个小于n的步长d1把表中全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组中进行直接插入排序:然后取第二个步长d2<d1,重复上       述过程,直到所取到的d1=1,即所有记录已放在同一组中,再进行直接插入排序,由于此时已经具有较好的局部有序性,故可以很快得到最终结果。到目前为         止,尚未求得一个最好的增量序列,希尔提出的方法是d1=n/2,di+1=?di/2? , 并且最后一个增量等于 1。
3.算法实现:
技术分享图片

补充:操作原理时间复杂度与选取的增量序列有关且所取增量序列的函数介于O(N*logN)和O(n2)之间增量序列有很多种取法,但是使增量序列中的值没有除1之外的公因子,并且增量序列中最后一个值必须为1。

4.插入排序伪代码

 

 1 void ShellSort (ElemType A[],int n){
 2 //对顺序表作希尔插入排序,基本算法和直接插入排序相比,做了以下修改:
 3 //1.前后记录位置的增量是dk,不是1
 4 //2.r[0]只是暂时存储单元,不是哨兵,当j<=0时,插入位置已到
 5       for(dk=n/2;dk>=1,dk=dk/2)                                   //步长变化
 6            for(i=dk+1;i<=n;++i) 
 7                  if(A[i].key<A[i-dk].key){                        //需将A[i]插入有序增量子表
 8                      A[0]=A[i];                                                       
 9                      for(j=i-dk;j>0&&A[0].key<A[j].key;j-=dk) 
10                           A[j+dk]=A[j];                           //记录后移,查找插入位置
11                      A[j+dk]=A[0];                                //插入
12                }//if
13   }

 

5.稳定性

   当相同关键字的记录被划分到不同的子表时,可能会改变它们之间的相对次序,因此,希尔排序是一种不稳定的排序方法。例如,表L=[3,2,2].经过一趟排序后,

L=[2,2,3],最终排序序列也是L=[2,2,3],显然2与2的相对次序已经发生了变化。

6.时间复杂度:O(N*logN)

 

?选择排序

1.算法思想

Step1:将待排序数组分为有序和无序两组(初始情况下有序组为空)

Step2:从左向右扫描无序组,找出最小的元素,将其放置在无序组的第一个位置。至此有序组++,无序组--;

Step3:重复Step2,直至无序组只剩下一个元素。

2.算法实现

技术分享图片

3.插入排序伪代码

 1 void ShellSort (ElemType A[],int n){
 2 //对表A作简单的选择排序,A[]从0开始放元素
 3       for(i=0;i<=n-1;i++){                                //一共进行n-1趟
 4           min=i;                                          //记录最小元素位置
 5               for(j=i+1;j<n;j++)                          //在A[i...n-1]中选择最小的元素                                    
 6                      if(A[j]<A[min])
 7                            min=j;                         //更新最小元素位置
 8 if(min!=i)  swap(A[i],A[min]);                            //在第n个元素交换
 9                         
10                }
11 }

4.时间复杂度: O(n2)

 

5.稳定性:

  选择排序的时间复杂度为O(n2),由于每次选择仅考虑某一位置上的数据情况,可能会破坏之前数据的相对位置,因此它是一种不稳定的排序方法。 例如:序列[9,9,1]第一次就将第一个[9]与[1]交换,导致第一个9挪动到第二个9后面。

  补充:简单选择排序的比较次数与序列的初始排序无关。假设待排序的序列有 n个元素,选择排序的赋值操作介于0和3(n - 1) 次之间; 则比较次数 永远都是n (n- 1) / 2; 而移动次数(即:交换操作)与序列的初始排序有关,介于 0 和 (n - 1) 次之间。当序列正序时,移动次数最少,为 0。当序列反序时,移动次数最多,为n - 1 次;逆序交换n/2次。选择排序的移动次数比冒泡排序少多了,由于交换所需CPU时间比 比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。

 

后续未完...

 



 

 

 

 

 

 

 

 

 

 


  




 

 










以上是关于数据结构——常见的十种排序算法的主要内容,如果未能解决你的问题,请参考以下文章

推荐 :关于机器学习的十种常用算法

十种常见排序算法

Java代码常见的十种错误

利用 Pandas 进行分类数据编码的十种方式

数据科学家用得最多的十种数据挖掘算法

数据结构十种排序算法