数据结构第十章 排序 总结

来源:互联网 发布:什么是excel数据透视表 编辑:程序博客网 时间:2024/05/22 16:44

排序算法的衡量

时间效率

比较次数与移动次数

空间效率

占内存辅助空间的大小

稳定性

假设 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。

这里写图片描述

原创粉丝点击