1、算法步骤
2、代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
void printVec(const T &t)
{
for (size_t i = 0; i < t.size(); i++)
{
<< t[i] << " ";
cout }
<< endl;
cout }
template <typename T>
void SimpleSelectSort(vector<T> &vec)
{
size_t i, j, k;
;
T tempfor (i = 0; i < vec.size(); i++)
{
= i; //初始化最小值所在位置
k // find min
for (j = i + 1; j < vec.size(); j++)
{
if (vec[j] < vec[k])
{
= j;
k }
}
if (k != i)
{
std::swap(vec[k], vec[i]);
}
}
}
int main(int argc, char **argv)
{
<int> vec = {6, 5, 4, 3, 2, 5, 6, 2, 5};
vector<int>(vec);
SimpleSelectSort<vector<int>>(vec);
printVec// 2 2 3 4 5 5 5 6 6
return 0;
}
3、算法分析
时间复杂度:需要n-1趟排序,每趟排序n-i次比较,总比较次数为`n(n-1)/2`,时间复杂度为O(n^2)
空间复杂度:O(1)
稳定性:不稳定
堆排序是一种树形选择排序算法,简单选择排序选出最小记录为O(n),而堆排序选择最小的记录只需要O(logn)
堆是一个完全二叉树,且如果每个节点的值都大于等于左右孩子的值,称为最大堆。如果每个节点的值都小于等于左右孩子的值,称为最小堆。
1、算法步骤
(1)构建初始堆
(2)堆顶和最后一个记录交换,即r[1]与r[n]交换,将r[1..n-1]重新调整
(3)堆顶和最后一个记录交换,即r[1]和r[n-1]交换,将r[1..n-2]重新调整为堆
(4)循环n-1次,得到一个有序序列
2、代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
void printVec(const T& t)
{
for (size_t i = 0; i < t.size(); i++)
{
<< t[i] << " ";
cout }
<< endl;
cout }
//下沉操作
void Sink(vector<int>& vec, size_t now,size_t size)
{
//如果vec[i]有孩子,则左孩子为2k+1(root下标1则2k),右孩子为2k+2(root下标1则2k)
while (2 * now + 1 < size) //有左孩子
{
size_t left = 2 * now + 1; //左孩子下标
if (left + 1 < size && vec[left] < vec[left + 1]) //有右孩子且左孩子小于右孩子
{
++;
left}
//现在left指向了左右孩子中比较值较大的那一个
if (vec[now] > vec[left]) //满足堆条件
{
break;
}
else //下沉到left位置
{
std::swap(vec[now], vec[left]);
}
//更新此时的位置
= left;
now }
}
//初始化堆
void CreateHeap(vector<int>& vec)
{
//完全二叉树从最后一个有孩子的节点进行调整
int mid = vec.size()+1 / 2;
= mid - 1;
mid for (int i = mid; i >= 0; i--)
{
(vec, i,vec.size()); //下沉vec[i]
Sink}
}
void HeapSort(vector<int>& vec,vector<int>&sortedVec)
{
<<"size of vec "<< vec.size() << endl;
cout (vec); //构建初始堆
CreateHeap<< "init tree" << endl;
cout (vec);
printVecint n = vec.size()-1;//最后一个节点
while (n >= 0) // n-1 twice
{
.push_back(vec[0]);
sortedVecstd::swap(vec[0], vec[n]);//将最后一个节点移动到根节点
--n;//堆中剩余节点
(vec, 0,n+1); //堆下沉 root节点
Sink}
}
int main(int argc, char** argv)
{
<int> vec = { 12, 16, 2, 30, 28, 20, 16, 6, 10, 18 };
vector<int> sortedVec;
vector(vec,sortedVec);
HeapSort<< "sorted Vec" << endl;
cout <vector<int>>(sortedVec);
printVec/*
size of vec 10
init tree
30 28 20 16 18 2 16 6 10 12
sorted Vec
30 28 20 18 16 16 12 10 6 2
*/
return 0;
}
3、算法分析
初始化一个堆,最后一个分支节点(n/2)到第一个节点进行下沉,下沉最大深度logn,所以构建堆上界为O(nlogn),大部分节点下沉小于O(nlogn),构建n个记录的堆,只需要少于2n次的比较和少于n次的交换,构建堆时间复杂度为O(n)。排序时,树的深度为logn,一共n-1次排序,总时间复杂度为O(nlogn)。
空间复杂度:O(1)
稳定性:堆排序时多次交换关键字,可能发生排序前后位置不一致情况,排序是非稳定排序方法。