数据结构第十章 排序 总结

排序算法的衡量

时间效率

比较次数与移动次数

空间效率

占内存辅助空间的大小

稳定性

假设 ki 是记录 Ri 中的关键字,kj 是记录 Rj 的中关键字,ki = kj 且在排序前的序列中,Ri 领先于Rj 。若在排序后的序列中 Ri 仍领先于 Rj,则称所用的排序方法是稳定的。

假设 ki 是记录 Ri 中的关键字,kj 是记录 Rj 的中关键字,ki = kj 且在排序前的序列中,Ri 领先于Rj 。若在排序后的序列中 Ri 仍领先于 Rj,则称所用的排序方法是稳定的。

直接插入排序

过程

整个排序过程为 n-1 趟插入。

1.先将序列中第1个记录看成是一个有序子序列。

2.取未排序子序列中的第一个元素,在已排序子序列中按简单顺序查找法(挨个比较)查找插入位置,边查找边移位。(重复此操作直到排序完成)

演示

用一个 n×n 的表格来表示。

[13] 6 3 31 9 27 5 ——-初始
[6 13] 3 31 9 27 5 ——-第一躺
[3 6 13] 31 9 27 5 ——-第二趟
[3 6 13 31] 9 27 5 ——-第三趟
[3 6 9 13 31] 27 5 ——-第四趟
[3 6 9 13 27 31] 5 ——-第五躺
[3 5 6 9 13 27 31] ——-第六躺

分析

时间复杂度: O(n2)

空间复杂度: O(1)

稳定性:稳定

实现

C语言实现

void InsertSort(SqList &L)
{
    int i,j;
    for(i=2; i<=L.length; ++i)
    if( L.r[i].key < L.r[i-1].key )
        { 
            L.r[0]=L.r[i];           // 复制为哨兵
            for(j=i-1; L.r[0].key<L.r[j].key; --j)
                L.r[j+1]=L.r[j];     // 第j个位置上的记录后移 
            L.r[j+1]=L.r[0];         //插入到正确位置
       }
 }

哨兵也可以单独的挑出来 , 数组从零开始。

void InsertSort(SqList &L)
{
    int i,j;
    r_type guard;
    for(i = 1; i <= L.length; ++i)
    if( L.r[i].key < L.r[i-1].key )
        { 
            guard = L.r[i];           // 复制为哨兵
            for(j = i-1; guard.key < L.r[j].key; --j)
                L.r[j+1] = L.r[j];     // 第j个位置上的记录后移 
            L.r[j+1] = guard;         //插入到正确位置
       }
 }

折半插入排序

过程

1.先将序列中第1个记录看成是一个有序子序列。

2.取未排序子序列中的第一个元素,在已排序子序列中按折半查找法查找插入位置,边查找边移位。(重复此操作直到排序完成)

插入位置的规则

当low>high时,low位置就是待插入的位置;

当r[mid]=r[i]时,mid+1位置就是插入位置;

分析

时间复杂度: O(n2) (比直接插入快)

空间复杂度: O(1)

稳定性:稳定

实现(待定)

希尔排序

过程

先将整个待排记录序列分割成若干子序列,分别进行直接插入排序。

待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

演示

划分序列为 {5,3,1}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

实现(待定)

冒泡排序(起泡排序)

过程

每趟不断将相邻两记录比较,并按“前小后大” 规则交换

演示

太简单了啊不想演示

这里写图片描述

分析

时间复杂度: O(n2)

空间复杂度: O(1)

稳定性:稳定

实现

C语言实现

void BubbleSort(SqList &L){
    a_type temp;
    for(i = 1; i < L.length; i++){
        c = 0;
        for(j = 1; j <= L.length-i; j++){
            if(L.a[j].key > L.a[j+1].key){
            temp = L.a[j]; 
            L.a[j] = L.a[j+1];
            L.a[j+1] = temp; //交换
            c++;
        }
        if(c == 0) break; //一趟没有发生交换,提前结束排序
    }   
}

快速排序

过程

1.任取一个元素 为中心(支点),一般刚开始取首位元素。

2.所有比它小的元素放在它前面,比它大的元素放在它后面,形成左右两个子表

3.对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个

演示

太难了我不想演示

这里写图片描述

我又想演示了

  1. high开始往前找比“枢纽”小的数,赋予low处。

  2. low开始往后找比“枢纽”大的数,赋予high处。

  3. 重复1,2步直到low >= high

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

实现

C语言实现

int Partition(SqList &L, int low,  int  high) 
{   //定位“枢纽”
    L.r[0] = L.r[low];    //将“枢纽”值赋予L.r[0]
    while(low < high) 
    { 
        /* 从high开始往前找比“枢纽”小的数,赋予`low`处 */
        while(low < high && L.r[high].key >= L.r[0].key)
            --high;
        L.r[low] = L.r[high];

        /* 从`low`开始往后找比“枢纽”大的数,赋予`high`处 */
        while(low < high && L.r[low].key <= L.r[0].key)  
            ++low;
        L.r[high] = L.r[low];
    }
    L.r[low]=L.r[0];     //将“枢纽”值赋予L.r[low]
    return low;          //返回“枢纽”位置
}

void QSort ( SqList &L, int low,  int  high ) 
{  
    if(low < high)
    {  
        pivotloc = Partition(L, low, high); //pivot:枢纽
        QSort(L, low, pivotloc-1);          //对左子表排序
        QSort(L, pivotloc+1, high);         //对右子表排序
    }
}

简单选择排序

过程

每一趟在 n-i +1个中选出关键码最小的对象, 作为有序序列的第 i 个记录

分析

时间复杂度: O(n2)

空间复杂度: O(1)

稳定性:稳定

演示

这里写图片描述

实现

C语言实现

void SelectSort(SqList &K)
{
    rtype temp;
    for (i=1; i<L.length; ++i)
    { 
        k = i;     //k为当前最小记录的位序
        for(j=i+1;j<=L.length ; j++)
            if(L.r[j].key < L.r[k].key) 
                k=j;  //就是大一学的“戴帽子”法
        if(k != i)
        L.r[i]←→L.r[k];            
    }  
}

树形排序

不考,我就先不写了啊

这里写图片描述

堆排序

堆:n个元素的序列{k1,k2,…,kn},当且仅当满足下列关系时,称为堆:

{kik2ikik2i1


{kik2ikik2i1

前者称为小顶堆(最小堆),后者称为大顶堆(最大堆),即堆顶元素(根)为最小值或最大值。

堆是一个线性结构。

如果将堆序列看成一个完全二叉树的线性存储结构,那么非终端结点的值均小于或大于左右孩子结点的值。

过程

1. 将待排序元素依次输入建立完全二叉树

2. 从最后一个非终端节点(第 n 元素)开始,至第一个元素,若存在比其小(大)的子节点,将其与最小(大)的子节点做替换,堆顶元素为最小(大),输出堆顶元素。

3. 将其与堆中最后一个元素(当前无序序列的最后一个元素)互换,并“剔除”最后一个元素。

4. 重复1,2,3步直到排序完成。

分析

时间复杂度: O(nlog2n)

空间复杂度: O(1)

稳定性:不稳定

适用于n 较大的情况

演示

这里写图片描述

待排序序列{30 60 8 40 70 12 10}

建大顶堆(从小大大排序)

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

归并排序

之前有专门总结:二路归并算法

基数排序

多关键字的排序

高位优先法

划分子序列的思想

低位优先法

分配再收集的思想

基数

d 为分量数。

设关键字的每个分量的取值范围均是:

C0kjCrd1(0j<d)

可能的取值个数 rd 称为基数。

链式基数排序

过程

建立一组关键字链表,用于分配和回收各位关键字;

从低位关键字到高位关键字依次进行分配和回收;

分配:根据当前关键字的取值将记录插入到相应的链表中;

回收:各链表“头尾相连”后回收所有记录作为下次分配的记录序;

演示

待排序序列:{47 82 40 07 59 38 69 05}
这里写图片描述
这里写图片描述

比较

这里写图片描述

快速排序平均状态下最快,但不稳定。

数据量大,要稳定,要快,归并。

好的,继续学kava。

这里写图片描述

排序作业 选择题(每题2分,共22分)。 1.若表R在排序前已按键值递增顺序排列,则(   )算法的比较次数最少。 A.直接插入排序            B.快速排序     C.归并排序                D.选择排序 2.对各种内部排序方法来说,(   )。 A.快速排序时间性能最佳                             B.归并排序是稳定的排序方法 C.快速排序是一种选择排序                          D.堆排序所用的辅助空间比较 3.  排序算法的稳定性是指(   )。 A.经过排序之后,能使值相同的数据保持原顺序中的相对位置不变。 B.经过排序之后,能使值相同的数据保持原顺序中的绝对位置不变。 C.排序算法的性能与被排序元素的数量关系不 D.排序算法的性能与被排序元素的数量关系密切 4. 如下序列中,(   )序列是顶堆。 A.  {4,5,3,2,1}               B.  {5,3,4,1,2}        C.  {1,2,3,4,5}               D.  {1,2,3,5,4} 5. 若将{3,2,5,4,1}排为升序,则实施快速排序一趟后的结果是(   )(其中,枢轴记录取首记录)。 A.  {1,2,3,4,5}                  B.  {1,2,4,5,3}        C.  {1,3,5,4,2}                  D.  {2,5,4,1,3} . 若将{1,2,3,4,5,6,7,9,8}排为升序,则(   )排序方法的“比较记录”次数最少。 A.  快速排序                   B.  简单选择排序     C.  直接插入排序               D.  冒泡排序 7. 若将{5,4,3,2,1}排为升序,则(   )排序方法的“移动记录”次数最多。 A.  快速排序                                B.  冒泡排序 C.  直接插入排序                       D.  简单选择排序 8. 用简单选择排序将顺序表{2,3,1 ,3′,2′}排为升序,实施排序1趟后结果是{1 ,3,2 ,3′,2′},则排序3趟后的结果是(   )。 A.  {1 ,2,3 ,3′,2′}                       B.  {1 ,2 ,2′,3 ,3′} C.  {1 ,2′,2 ,3 ,3′}                      D.  {1 ,2 ,2′,3′,3 } 9.下列排序算法中,(    )排序在某趟结束后不一定选出一个元素到其最终的位置上。 A.选择             B.冒泡           C.归并           D.堆 10.下列排序算法中,稳定的排序算法是(  )。 A.堆排序                B.直接插入排序   C.快速排序              D.希尔排序 11.堆排序时间复杂度是(    )。 A.O(n*n)                 B.O(n*log n)       C.O(n)                   D.O(log n) 填空题(每空4分,共4分)。 对n个元素进行归并排序,空间复杂度为         。 综合题(共24分)。 1. (共12分)有一组待排序关键字如下: (54,38,96,23,15,72,60,45,83) 分别写出希尔排序(d=5)、快速排序、堆排序、归并排序第一趟升序排序后的结果(其中堆排序的第一趟指序列完成初始建堆、将堆顶元素置为最末位置后其余元素调整为堆的结果)(每个3分)。 希尔排序:   快速排序: 堆排序: 归并排序:  2. (共12分)已知数据序列为(12,5,9,20,6,31,24),对该项数据序列进行排序,分别写出直接插入排序、简单选择排序、快速排序、堆排序、二路归并排序及基数排序第一趟升序排序结果(其中堆排序的第一趟指序列完成初始建堆、将堆顶元素置为最末位置后其余元素调整为堆的结果)(每个2分)。 直接插入排序: 简单选择排序: 快速排序: 堆排序: 二路归并排序: 基数排序:    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值