设为首页 加入收藏

TOP

数据结构——常见的十种排序算法(一)
2018-12-12 02:10:44 】 浏览:314
Tags:数据结构 常见 排序 算法

一、常见的十种排序算法:

  冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、桶排序、基数排序
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(n²)

 

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

1.算法提出:

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

补充:操作原理时间复杂度与选取的增量序列有关且所取增量序列的函数介于O(N*logN)和O(n²)之间增量序列有很多种取法,但是使增量序列中的值没有除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(n²),由于每次选择仅考虑某一位置上的数据情况,可能会破坏之前数据的相对位置,因此它是一种不稳定的排序方法。 例如:序列  [9,9,1]第一次就将第一个[9]与[1]交换,导致第一个9挪动到第二个9后面。

5.时间复杂度: O(n²)

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

?堆排序

1.引入概念
 
堆是一棵顺序存储的完全二叉树。其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小根堆。
其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大根堆。
举例来说,对于n个元素的序列{R0, R1, ... , Rn}当且仅当满足下列关系之一时,称之为堆: 

2.算法思想

    堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
如图:


3.算法实现(大顶堆)
注:若n为数组的个数,那么就从2/n
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇错排公式浅谈(推导+应用) 下一篇C语言入门教程-(1)简介及搭建环境

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目