排序之选择排序

二、选择排序
1、选择排序(区间在不断地变小 )
基本思想:
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 (首先,选出最小的数放在第一位,然后选择第二小的数,放在第二位;以此类推,直到所有的数从小到大排列.那么,对于大小为N的数组需要N-1轮选择过程。第i轮选取第i小的数,请将其放在第i个位置上。)

注意点:
选择排序与冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不合法的元素位置,从而将当前最小(大)元素放到合适的位置;而选择排序每遍历一次都记住了当前最小(大)元素的位置,最后仅需一次交换操作即可将其放到合适的位置

// 选择排序(普通版)
void selectSort(int* a, size_t n)
{
      int maxSpace = n - 1;          //用来存放最大数的位置
      int i;                         //在找maxpos的一个下标
      int maxPos;                    //找到的最大数的下标
      for (; maxSpace > 0; maxSpace--)
      {
            maxPos = 0;
            for (i = 0; i <= maxSpace; i++)
            {
                  if (a[i] > a[maxPos])
                  {
                        maxPos = i;
                  }
            }
            int tmp = a[maxSpace];
            a[maxSpace] = a[maxPos];
            a[maxPos] = tmp;
      }

}

这里写图片描述

选择排序升级版(每次分别选择最大和最小的数字,交换两者)
void Swap(int &a, int &b)
{
      int tmp;
      tmp = a;
      a = b;
      b = tmp;
}
// 选择排序(升级版)
void selectSort_up(int *a, int n)
{
      int minSpace = 0;        //(1)用来放最小数的下标;(2)查找的是左区间,闭区间
      int maxSpace = n - 1;    //(1)用来放最大数的下标;(2)查找的是右区间,闭区间
      int minPos;             // 区间内找到的最小数的下标
      int maxPos;             // 区间内找大的最大数的小标
      int i;                 //  i 为在区间遍历时用到的下标
      while (minSpace < maxSpace)    // 倘若等于了就说明此时只有一个数了
      {
            minPos = minSpace;
            maxPos = maxSpace;
            for (i = minSpace; i <= maxSpace; i++)
            {
                  if (a[i] > a[maxPos])
                        maxPos = i;
                  if (a[i] < a[minPos])
                        minPos = i;
            }
            // 此时找到了区间内最大的和最小的,交换两者
            Swap(a[minSpace], a[minPos]);
            //BUG
            if (minSpace == maxPos)
                  maxPos = minPos;
            Swap(a[maxSpace], a[maxPos]);
            minSpace++;
            maxSpace--;
      }
}

2、堆排序(一种不稳定的排序算法)
以前就写过有关堆的知识点,有兴趣的可戳链接
https://blog.csdn.net/apt1203JN/article/details/79720005
(1)先创建好堆。升序排列时创建大堆,降序排列时创建小堆

  • a、从后往前建堆
  • b、依次向下调整:
    (2)排序(就是让刚才建好的大堆or小堆变得有序起来)。具体过程如下
  • a、把堆顶元素array[0]和堆的最后一个元素交换
  • b、最堆元素个数减一(这样就是为了避开刚交换的元素去调整剩下的元素)
  • c、当交换元素之后,堆肯定会不满足最堆的定义,此次需要调整节点
    这里写图片描述
注:重复上图的过程一直到堆排列有序

//调整堆
      void AdjustHeap(int array, size_t size, size_t parent)
      {
            //标记最大的孩子,默认左孩子最大
            size_t child = parent * 2 + 1;
            while (child < size)
            {
                  //找左右孩子中最大的孩子
                  if (child + 1 < size && array[child + 1] > array[child])
                  {
                        child = child + 1;
                  }
                  //用最大的孩子去检测双亲
                  if (array[parent] < array[child])
                  {
                        swap(array[parent], array[child]);
                        parent = child;
                        child = parent * 2 + 1;
                  }
                  else
                        return;
            }
      }

//堆排序
      void HeapSort(int* array, size_t size)
      {
            //创建堆
            //倒数第一个非叶子节点的位置
            int root = (size - 2) / 2;
            for (; root >= 0; --root)
            {
                  AdjustHeap(array, size, root);
            }
            //堆排序
            for (int i = 0; i < size; i++)
            {
                  swap(array[0], array[size - i - 1]);
                  AdjustHeap(array[0], size - i - 1, 0)
            }
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值