排序(二)--选择排序:选择排序、堆排序

一、选择排序(以升序为例)

1.算法思想

在整个区间中找出排序码最小的元素,如果这个元素不是这组序列中的第一个元素,那么将它和第一个元素进行交换,使得最小的元素就在第一个位置,然后缩小区间,循环执行上述操作,只到区间中只剩下一个元素。

注意:选择排序和冒泡排序有相似之处,以升序为例,都是将最小的数放在最前面。但是不同之处在于冒泡排序是对于两个相邻数进行比较和交换,而选择排序是对于整体进行排序。

2.算法的具体步骤

(1)在区间中找到关键码最小的元素。
(2)如果不是待排序区间的第一个元素,则和带排序区间第一个元素交换。
(3)缩小待排序区间。

3.图解举例

这里写图片描述

4.代码实现
void SelectSort(int* arr, int size)
{
    if (arr == NULL || size <= 0)
        return;

    for (int i = 1; i < size; i++)
    {
        int minindex = i;//i下标位置的元素是最小的
        int start = i - 1;//从未排序的最小区间的下标开始

        while (minindex < size)
        {
            if (arr[minindex] < arr[start])
            {
                swap(arr[minindex], arr[start]);
                ++minindex;
            }
        }
    }
}
5.其他

(1)时间复杂度:O(n^2)
(2)空间复杂度:O(1)
(3)稳定性:不稳定

6.动态图

这里写图片描述

二、堆排序(以升序为例)
1.算法思想
  • 堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构。
  • 堆排序就是利用堆这种数据结构实现的一种排序算法,堆是完全二叉树的一种。
    堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
    • 堆有以下几个特点:
      (1)最大堆:每一个父亲节点的值都大于两个孩子节点的值。
      (2)最小堆:每一个父亲节点的值都小于两个孩子节点的值。
      这里写图片描述
2.算法的具体步骤

堆排序的基本思想就是利用了这种结构,如果我们需要升序:
(1)将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
(2)将堆顶元素与末尾元素交换,将最大元素”沉”到数组末端;
(3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

3.图解举例

这里写图片描述

4.代码实现
//堆排序
void AjustDown(int* arr, int pos, int size)//向下调整
{
    int parent = pos;
    int child = parent * 2 + 1;//得到的是左子树

    while (child <= size)
    {
        if (child<size&&arr[child + 1]>arr[child])
        {
            child++;
        }

        if (arr[parent] < arr[child])
        {
            swap(arr[parent], arr[child]);
            arr[parent] = arr[child];
            child = child * 2 + 1;
        }
        else
        {
            break;
        }
    }
}

void AjustDown_t(int* arr, int size)//选择离叶子结点最近的父结点
//该函数的作用是:从离叶子结点最近的父节点开始使用向下调整法一直调整,直到找到最大的元素
{
    int parent = (size - 2) / 2;

    while (parent >= 0)
    {
        AjustDown(arr, parent, size-1);
        parent--;
    }
}

void HeapSort(int* arr, int size)//堆排序
{
    //使得对按照向下调整的方法排序
    AjustDown_t(arr, size);

    while (size > 1)
    {
        //进行交换
        int tmp = arr[0];
        arr[0] = arr[size - 1];
        arr[size - 1] = tmp;
        size--;

        //重新调整堆结构
        AjustDown_t(arr, size);
    }
}
5.其他

(1)时间复杂度:O(NlogN)

因为堆中元素的个数是N,所以堆的高度是logN,那么比较次数就是2logN,交换的次数是N次.

(2)空间复杂度:O(1)
(3)稳定性:不稳定

6.动态图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/cherrydreamsover/article/details/81159136