内部排序算法总结(下)C++实现

Posted Rainbowman 0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内部排序算法总结(下)C++实现相关的知识,希望对你有一定的参考价值。

上节总结了基于交换的排序:冒泡排序和快速排序;以及基于插入的排序:简单插入排序和希尔排序。内部排序算法总结(上)【C++实现】

本节总结两种基于选择的排序:选择排序和堆排序

一、 基于选择的排序

1. 选择排序

思想

(1)固定数组中的第一个元素,分别与剩余的所有元素进行比较,从而找到序列中的最小值和固定元素交换,如果固定元素就是最小值,则无需交换。

(2)在剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。

时间复杂度

平均最好最坏
O(n2)O(n2)O(n2)

动画演示

在这里插入图片描述
代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void selectSort(vector<int>& nums)
{
    int i, j, minn;
    for(i=0; i<nums.size();i++){
        minn = i;
        for(j=i+1; j<nums.size();j++){
            if(nums[j]<nums[minn])  minn = j;
        }
        swap(nums[i], nums[minn]);
    }
}

int main()
{
    int n;
    vector<int> nums;
    while(cin>>n){
        nums.push_back(n);
    }
    selectSort(nums);
    for(int num : nums){
        cout<<num<<" ";
    }
}

P.s:选择排序VS插入排序:
选择排序:

从当前元素开始,向后遍历,找到最小的元素,与当前元素交换位置。

插入排序:

从当前元素开始,向前遍历(前面的数组已经为一有序数组),找到第一个比当前元素小的元素,将当前元素插在该元素后面。

因此,两种排序方法在实现方面的比较明显的区别就是,选择排序是向后遍历,而插入排序是向前遍历。在思想方面,选择排序是选择出最小的元素,然后与当前元素交换,而插入排序需要将元素一步步后挪,然后将当前元素插入相应位置。

2. 堆排序

思想

(1)什么是堆?

堆:符合以下两个条件之一的完全二叉树

每个结点的值都大于其左孩子和右孩子结点的值,称之为大根堆;每个结点的值都小于其左孩子和右孩子结点的值,称之为小根堆。如下图

图片来源

在这里插入图片描述
我们用数组的方式来存储完全二叉树,如下所示

在这里插入图片描述
这里我们要用到完全二叉树的三条重要性质:

(1)对于完全二叉树中的第 i 个数,它的左子节点下标:left = 2i + 1
(2)对于完全二叉树中的第 i 个数,它的右子节点下标:right= left + 1
(3)对于有 n 个元素的完全二叉树(n≥2)(n≥2),它的最后一个非叶子结点的下标:n/2 - 1

【2】堆排序的思想:

(1)从下到上(从最后一个非叶子结点【下标为n/2-1】到根【下标为0】)构造一个大顶堆;

(2)取根顶数字:

交换根结点(数组的首元素,为当前完全二叉树的最大值)和最后一个叶子节点(数组的尾元素);

P.s:
(1)即把最大的值移到数组的末尾。
(2)根结点交换到数组的后面位置后,相当于从大顶堆中脱离了,以后构造大顶堆时不再考虑该元素。

(3)再从上到下将剩余元素构造成一个大顶堆(剩余元素指不包含(2)中交换到数组末尾的根结点的元素)

(4)重复上述操作,直到所有元素都从大顶堆中脱离。

时间复杂度

平均最好最坏
O(nlog(n))O(nlog(n))O(nlog(n))

动画效果

在这里插入图片描述
代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// root为根结点下标
// 将以root为根结点的完全二叉树调整为大顶堆
void adjustHeap(vector<int>& nums, int root, int len)
{
    int left = root*2+1, right = root*2+2;
    int maxx = root;
    if(left<len && nums[maxx]<nums[left])   maxx = left;
    if(right<len && nums[maxx]<nums[right])   maxx = right;
    if(maxx!=root){
        swap(nums[maxx], nums[root]);
        adjustHeap(nums, maxx, len);
    }
}

void buidHeap(vector<int>& nums)
{
    int len = nums.size();
    for(int i=len/2-1; i>=0; i--){
        adjustHeap(nums, i, len);
    }
    for(int i=len-1; i>=0; i--){
        swap(nums[0], nums[i]);
        adjustHeap(nums, 0, i);
    }
}

int main()
{
    int n;
    vector<int> nums;
    while(cin>>n){
        nums.push_back(n);
    }
    buidHeap(nums);
    for(int num : nums){
        cout<<num<<" ";
    }
}

以上是关于内部排序算法总结(下)C++实现的主要内容,如果未能解决你的问题,请参考以下文章

七种常见经典排序算法总结(C++实现)

七种常见经典排序算法总结(C++)

关于常用排序算法的一个总结

算法笔记 排序算法完整介绍及C++代码实现 HERODING的算法之路

数据结构之排序算法

快速排序(QuickSort),归并排序(MergeSort),堆排序(HeapSort)典型C++代码实现总结