排序——选择排序

简介: 排序——选择排序

选择排序


简单选择排序

基本思想

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

算法实现

void SelectSort(SqList &L){
    // 对记录序列R[1.. L.length]作简单选择排序
    for(i = 1; i <= L.length; i++){
        // 选择第 i 小的记录,并交换到位
        k = i;
        for(j = i + 1; j <= L.length; ++j)
            if(L.r[j].key < L.r[k].key) k = j;
        if(k != i) Swap(L.r[i], L.r[k]);  // 交换
    }
}

算法分析

  • 时间复杂度:O(n^2)

    • 移动次数:

      • 最好情况:0
      • 最坏情况:3(n-1)
  • 空间复杂度: O(1)
  • 稳定性: 稳定

树形选择排序

基本思想

  • 取得 n 个对象的关键码,进行两两比较,得到 n/2 个比较的优胜者(关键码小者),作为第一步比较的结果保留下来。
  • 这 n/2 个对象再进行关键码的两两比较,…,如此重复,直到选出一个关键码最小的对象为止。

算法分析

  • 含有n个叶子节点的完全二叉树的深度为log2 n+1,则选择排序的每一趟都需作log2n次比较,排序的时间复杂度O(nlog2n)
  • 需要辅助存储空间较多(n-1),和最大值作多余的比较等等。
改进:简单选择排序没有利用上次选择的结果,是造成速度满的重要原因。如果,能够加以改进,将会提高排序的速度。

堆排序

  • 堆:把待排序的数据元素存放在数组中r[1…n],把r看成是一棵完全二叉树,每个结点表示一个记录。r[i]结点的左孩子是r[2i],右孩子是r[2i+1]。
  • r[i].key<=r[2i].key,并且 r[i].key<=r[2i+1].key,则称此完全二叉树为堆。(小根堆)
  • r[i].key>=r[2i].key,并且 r[i].key>=r[2i+1].key,则称此完全二叉树为堆。(大根堆)

在这里插入图片描述

基本思想

  • 将无序序列建成一个堆
  • 输出堆顶的最小(大)值
  • 使剩余的n-1个元素又调整成一个堆,则可得到n个元素的次小值
  • 重复执行,得到一个有序序列

无序序列建成堆

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如何在输出堆顶元素后调整,使之成为新堆?

  • 输出堆顶元素后,以堆中最后一个元素替代之
  • 将根结点与左、右子树根结点比较,并与小者交换
  • 重复直至叶子结点,得到新的堆

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法实现

void HeapAdjust(HeapType &H, int s, int m){
    // 已知 H.r [s..m]中记录的关键字除 H.r [s] 之外均
    // 满足堆的特征,本函数自上而下调整 H.r [s] 的
    // 关键字,使 H.r [s..m] 也成为一个大顶堆。
    rc = H.r[s];  // 暂存 H.r [s]
    for(j = 2 * s; j <= m; j *= 2){
         // j 初值指向左孩子
        // 自上而下的筛选过程;
        if(j < m && H.r[j].key < H.r[j + 1].key) ++j;
        // 左/右“子树根”之间先进行相互比较
        // 令 j 指示关键字较大记录的位置
        if ( rc.key >= H.r[j].key )  break; 
        // 再作“根”和“子树根”之间的比较,
        // 若“>=”成立,则说明已找到 rc 的插
        // 入位置 s ,不需要继续往下调整
        H.r[s] = H.r[j];   s = j;    
        // 否则记录上移,尚需继续往下调整

    }
    H.r[s] = rc;  // 将调整前的堆顶记录插入到 s 位置
}

void HeapSort ( HeapType &H ) {
    // 对顺序表 H 进行堆排序
    for(i = H.length / 2; i > 0; --i)
        HeapAdjust(H, i, H.length);  // 建大顶堆
    for(i = H.length; i > 1; --i){
        Swap(H.r[1], H.r[i])           
        // 将堆顶记录和当前未经排序子序列
        // H.r[1..i]中最后一个记录相互交换
        HeapAdjust(H, 1, i-1);  // 将H.r[1...i-1]重新调整为大顶堆
    }
}

算法分析

  • 时间效率:O(nlog2n)
  • 空间效率:O(1)
  • 稳定性:不稳定
适用于n 较大的情况
目录
相关文章
|
7月前
|
算法 搜索推荐
排序——选择排序
排序——选择排序
76 0
|
7月前
|
搜索推荐 算法 Shell
排序——插入排序
排序——插入排序
50 0
|
算法 搜索推荐 索引
排序篇(二)----选择排序
排序篇(二)----选择排序
38 0
|
存储 搜索推荐 测试技术
排序篇(一)----插入排序
排序篇(一)----插入排序
52 0
|
算法 搜索推荐
排序——冒泡排序
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
|
搜索推荐
排序(2)之选择排序
继插入排序后,今天小编就给大家另一个模块,选择排序的学习,那么话不多说,我们直接进入正题。
122 0
|
存储 搜索推荐 测试技术
排序(1)之插入排序
从今天小编就开始给大家介绍排序的内容,对于排序内容我们一共分,插入,选择,交换,归并这几个大类,那么今天小编给大家带来的就是插入排序
105 0
|
索引
掌握常见的几种排序-选择排序
选择排序是一种简单的排序,时间复杂度是O(n^2),在未排序的数组中找到最小的那个数字,然后将其放到起始位置,从剩下未排序的数据中继续寻找最小的元素,将其放到已排序的末尾,以此类推,直到所有元素排序结束为止。
122 0
掌握常见的几种排序-选择排序
|
算法
排序——快速排序
排序——快速排序
125 0
排序——快速排序
|
算法 Shell
排序——希尔排序
排序——希尔排序
133 0
排序——希尔排序