内部排序算法总结(下)C++实现
Posted Rainbowman 0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内部排序算法总结(下)C++实现相关的知识,希望对你有一定的参考价值。
上节总结了基于交换的排序:冒泡排序和快速排序;以及基于插入的排序:简单插入排序和希尔排序。内部排序算法总结(上)【C++实现】
本节总结两种基于选择的排序:选择排序和堆排序
CONTENT
一、 基于选择的排序
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++实现的主要内容,如果未能解决你的问题,请参考以下文章