手撕排序算法2:堆排序和直接选择排序(下)

简介: 手撕排序算法2:堆排序和直接选择排序(下)

二.直接选择排序

1.算法剖析

基本思想: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完.

代码实现

void SelectSort(int* a, int n)
{
  int i = 0;
  for (i = 0; i < n; i++)//i:排好序的元素的最大下标
  {
    int j = 0;
    int min = i;//从i下标位置开始选出最小值
    for (j = i; j < n; j++)
    {
      if (a[min] > a[j])//更新最小值
      {
        min = j;
      }
    }
    Swap(&a[min], &a[i]);//把最小值放在i下标位置处
  }
}

可见,时间复杂度是O(N^2),

而且,需要注意的是直接选择排序的双层for循环中并没有出现break

也就是说无论待排序的序列是有序还是无序还是部分有序

直接选择排序并不考虑这些,它是找最大值(或者最小值)依次放到数组的起始位置

2.优化版本算法剖析

上面代码不难理解,下面我们来给大家看一个优化版本的直接选择排序,这个优化版本比上一个版本快一倍,不过时间复杂度也是O(N^2)

void Swap(int* n1, int* n2)
{
  int tmp = *n1;
  *n1 = *n2;
  *n2 = tmp;
}
void SelectSort(int* a, int n)
{
  int begin = 0;
  int end = n - 1;
  while (begin < end)
  {
    int min_i = begin;
    int max_i = begin;
    for (int i = begin; i <= end; i++)
    {
      if (a[i] < a[min_i])
      {
        min_i = i;
      }
      if (a[i] > a[max_i])
      {
        max_i = i;
      }
    }
    Swap(&a[begin], &a[min_i]);
    //如果begin跟max_i重叠,需要修正一下max_i的位置
    if (begin == max_i)
    {
      max_i = min_i;
    }
    Swap(&a[max_i], &a[end]);
    begin++;
    end--;
  }
}

这个优化版本的思想是:

1.通过begin和end逐步缩小待排序的范围,当begin>=end时,排序完成

2.通过min_i和max_i选择出[begin,end]内的最大值和最小值,并把最小值与begin位置处的数据交换,把最大值与end位置处的数据交换.

下面是不修正max_i的代码

void Swap(int* n1, int* n2)
{
  int tmp = *n1;
  *n1 = *n2;
  *n2 = tmp;
}
void SelectSortUpper(int* a, int n)
{
  int begin = 0;
  int end = n - 1;
  while (begin < end)
  {
    int min_i = begin;
    int max_i = begin;
    int i = 0;
    for (i = begin; i <= end; i++)
    {
      if (a[min_i] > a[i])
      {
        min_i = i;
      }
      if (a[max_i] < a[i])
      {
        max_i = i;
      }
    }
    Swap(&a[min_i], &a[begin]);
    Swap(&a[max_i], &a[end]);
    begin++;
    end--;
  }
}

下面给大家画图解释一下为什么要修正max_i的位置

3.时间复杂度和稳定性

1.时间复杂度

直接选择排序的时间复杂度是O(N^2)

都是等差数列

未优化版本:

N+(N-1)+(N-2)+… -> O(N^2)

优化版本

N+(N-2)+(N-4)+… -> O(N^2)

2.对直接选择排序的评价

在这里我们可以看出:插入排序为1698ms,直接选择排序为4533ms,同样时间复杂度都是O(N^2),但是却相差这么大,

所以也就是说直接选择排序效率非常差,是效率最差的排序算法,

后面讲到冒泡排序(时间复杂度也是O(N^2))的时候我们还要再对比一下这三者的时间复杂度.

3.稳定性

直接选择排序不具有稳定性,下面给大家举一个例子

以上就是堆排序和直接选择排序的讲解,希望能给大家带来帮助

相关文章
|
5月前
|
存储 算法 搜索推荐
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
专攻软考高频算法,深度解析二分查找、堆排序、快速排序核心技巧,对比九大排序算法,配套动画与真题,7天掌握45%分值模块。
264 1
软考算法破壁战:从二分查找到堆排序,九大排序核心速通指南
|
7月前
|
搜索推荐
选择排序与其它排序算法比较
选择排序与冒泡排序同属O(n²)排序算法,但选择排序不稳定。相比堆排序,虽每轮均选最大元素,但选择排序基于线性结构,效率较低,而堆排序利用大顶堆结构提升了选择效率。
126 0
|
12月前
|
存储 搜索推荐 算法
算法系列之排序算法-堆排序
堆排序(Heap Sort)是一种基于堆数据结构的比较排序算法。它的时间复杂度为 $O(nlogn)$,并且是一种原地排序算法(即不需要额外的存储空间)。堆排序的核心思想是利用堆的性质来维护一个最大堆或最小堆,然后逐步将堆顶元素(最大值或最小值)取出,放到数组的末尾,最终得到一个有序的数组。
349 8
算法系列之排序算法-堆排序
|
算法 搜索推荐
算法之堆排序
本文介绍了堆排序算法的原理和实现,通过构建最大堆或最小堆,利用堆的性质进行高效的排序,并提供了具体的编程实现细节和示例。
156 1
算法之堆排序
|
搜索推荐 Java Go
深入了解选择排序算法
深入了解选择排序算法
171 4
|
搜索推荐
冒泡排序(Bubble Sort)以及选择排序(Selection Sort)和快速排序(Quick Sort)详细解析
冒泡排序(Bubble Sort)以及选择排序(Selection Sort)和快速排序(Quick Sort)详细解析
286 1
|
算法 搜索推荐
数据结构与算法学习十八:堆排序
这篇文章介绍了堆排序是一种通过构建堆数据结构来实现的高效排序算法,具有平均和最坏时间复杂度为O(nlogn)的特点。
502 0
数据结构与算法学习十八:堆排序
|
算法 搜索推荐
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
本文介绍了冒泡排序、选择排序和插入排序三种基础排序算法的原理、实现代码和测试结果。
526 0
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
|
算法 Java Go
深入了解堆排序算法
深入了解堆排序算法
305 1
|
搜索推荐 算法
【排序算法(一)】——插入排序,选择排序 —> 深层解析
【排序算法(一)】——插入排序,选择排序 —> 深层解析

热门文章

最新文章