//C++学习笔记_21 优先级队列实现-堆积树-堆排序
#include<vector>
#include<iostream>
#include<string>
#include<deque>
#include<queue>
using namespace std;
class MyPriQue_V0
{
private:
vector<int> elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue_V0(){}
int size() { return elems.size();}
bool empty() { return elems.empty();}
void push(int x)
{
//1: 把新插入元素 x 放在最后面
elems.push_back(x);
int iChild = size() - 1; //x这个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0) {//iChlid 是根节点了,就不要往上找了
//2:x 与 它的父节点比较
if (elems[iChild] > elems[iFather]){
//2 - 1:大于父节点,则 交换 x 和 父节点的值
int tmp = elems[iChild];
elems[iChild] = elems[iFather];
elems[iFather] = tmp;
}
else break;//2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//3:循环执行 第二步,直到x位于根节点
}
void pop(){
//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
swap(elems.front(), elems.back());
elems.pop_back();
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) {//存在子节点的情况才进行比较,无子节点就没有比较的必要了
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size() && elems[iChild + 1] > elems[iChild]){
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
//2 - 1:如果 x 大于等于 subMax ,结束调整(已经是大堆)
if (elems[iFather] >= elems[iChild]) break;
else{//2 - 2:如果 subMax 比 x 大,交换 x 和 subMax
int tmp = elems[iFather];
elems[iFather] = elems[iChild];
elems[iChild] = tmp;
}
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//4: 循环第二步,直到 x 没有子节点
}
int& top() { return elems.front();}//返回堆顶的元素
void Print(){
vector<int>::iterator it;
for (it = elems.begin(); it != elems.end(); it++){
cout << *it << " ";
}
cout << endl;
}
};
//写成模板形式
template<typename T>
class MyPriQue_V1
{
private:
vector<T> elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue_V1(){}
int size() { return elems.size();}
bool empty() { return elems.empty();}
void push(T x) {
//1: 把新插入元素 x 放在最后面
elems.push_back(x);
int iChild = size() - 1; //x这个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0) {//iChlid 是根节点了,就不要往上找了
//2:x 与 它的父节点比较
if (elems[iChild] > elems[iFather]) {
//2 - 1:大于父节点,则 交换 x 和 父节点的值
T tmp = elems[iChild];
elems[iChild] = elems[iFather];
elems[iFather] = tmp;
}
else break;//2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//4:循环执行 第二步,直到x位于根节点
}
void pop(){//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
swap(elems.front(), elems.back());
elems.pop_back();
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) {//存在子节点的情况才进行比较,无子节点就没有比较的必要了
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size() && elems[iChild + 1] > elems[iChild]){
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
//2 - 1:如果 x 大于等于 subMax ,结束调整(已经是大堆)
if (elems[iFather] >= elems[iChild]) break;
else{//2 - 2:如果 subMax 比 x 大,交换 x 和 subMax
T tmp = elems[iFather];
elems[iFather] = elems[iChild];
elems[iChild] = tmp;
}
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//4: 循环第二步,直到 x 没有子节点
}
T& top() { return elems.front();}//返回堆顶的元素
void Print(){
typename vector<T>::iterator it;
for (it = elems.begin(); it != elems.end(); it++){
cout << *it << " ";
}
cout << endl;
}
};
//流程优化
//插入:只需要找新插入节点的最终位置
// 找最终位置的过程,把这条线路的节点下移 (V1版本的新节点上移)
//删除:只需要找新的根节点的最终位置
// 找最终位置的过程,把这条线路上的节点上移 (V1 版本的头结点下移)
template<typename T>
class MyPriQue_V2
{
private:
vector<T> elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue_V2(){}
int size() { return elems.size();}
bool empty() { return elems.empty();}
void push(T x) { //1: 把新插入元素 x 放在最后面
elems.push_back(x); //或者 elems.resize(size()+1); 扩充一个元素
int iChild = size() - 1; //最后一个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0) {//iChlid 是根节点了,就不要往上找了
//2:x 与 当前节点的父节点比较
if (x > elems[iFather]){
//流程优化,不做交换,只是把父节点下移
//2 - 1:大于父节点,则 把父节点下移
elems[iChild] = elems[iFather];
}
else break;//2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//3:循环执行 第二步,直到x位于根节点
//循环完成后,iChild 位置,就是 x 这个值的需要保存的最终位置
elems[iChild] = x;
}
void pop(){
//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
//先不删除最后一个节点,用于暂存最终需要保存的元素
//处理完毕后,再删除
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) {//存在子节点的情况才进行比较,无子节点就没有比较的必要了
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size() && elems[iChild + 1] > elems[iChild]){
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
if (elems.back() >= elems[iChild]) break;//直接个最后一个节点比较
else elems[iFather] = elems[iChild];
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//4: 循环第二步,直到 没有子节点
elems[iFather] = elems.back();
elems.pop_back();//最后,删除末尾节点
}
T& top() { return elems.front();}//返回堆顶的元素
void Print() {
typename vector<T>::iterator it;
for (it = elems.begin(); it != elems.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
};
//统一比较运算符,元素比较,全部用 < 符号来比较
//底层容器使用模板
template<typename T, typename Container=vector<T>>
class MyPriQue_V3
{
private:
Container elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue_V3(){}
int size() { return elems.size();}
bool empty() { return elems.empty();}
void push(T x) {
//1: 把新插入元素 x 放在最后面
elems.push_back(x); //或者 elems.resize(size()+1); 扩充一个元素
int iChild = size() - 1; //最后一个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0) { //iChlid 是根节点了,就不要往上找了
//2:x 与 当前节点的父节点比较
if (elems[iFather] < x) {
//流程优化,不做交换,只是把父节点下移
//2 - 1:大于父节点,则 把父节点下移
elems[iChild] = elems[iFather];
}
else break; //2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//4:循环执行 第二步,直到x位于根节点
//循环完成后,iChild 位置,就是 x 这个值的需要保存的最终位置
elems[iChild] = x;
}
void pop(){
//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
//先不删除最后一个节点,用于暂存最终需要保存的元素
//处理完毕后,再删除
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) //存在子节点的情况才进行比较,无子节点就没有比较的必要了
{
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size() && elems[iChild] < elems[iChild+1]){
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
if (!(elems.back() < elems[iChild])) break;//直接个最后一个节点比较
else elems[iFather] = elems[iChild];
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//3: 循环第二步,直到 没有子节点
elems[iFather] = elems.back();
elems.pop_back();//最后,删除末尾节点
}
T& top() { return elems.front();} //返回堆顶的元素
void Print() {
typename Container::iterator it;
for (it = elems.begin(); it != elems.end(); it++){
cout << *it << " ";
}
cout << endl;
}
};
//增加比较规则,使用 仿函数,作为一个模板类型
template<typename T, typename Container = vector<T>, typename RULE=less<T>>
class MyPriQue_V4
{
private:
Container elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue_V4(){}
int size() { return elems.size();}
bool empty() { return elems.empty(); }
void push(T x) {
//1: 把新插入元素 x 放在最后面
elems.push_back(x); //或者 elems.resize(size()+1); 扩充一个元素
int iChild = size() - 1; //最后一个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0){ //iChlid 是根节点了,就不要往上找了
//2:x 与 当前节点的父节点比较
if (/*elems[iFather] < x*/
RULE()(elems[iFather], x)
) //构造堆使用的比较规则,比较规则改变了,则堆也改变了
{
//流程优化,不做交换,只是把父节点下移
//2 - 1:大于父节点,则 把父节点下移
elems[iChild] = elems[iFather];
}
else break;//2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//3:循环执行 第二步,直到x位于根节点
//循环完成后,iChild 位置,就是 x 这个值的需要保存的最终位置
elems[iChild] = x;
}
void pop(){
//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
//先不删除最后一个节点,用于暂存最终需要保存的元素
//处理完毕后,再删除
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) {//存在子节点的情况才进行比较,无子节点就没有比较的必要了
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size()
&& /*elems[iChild] < elems[iChild + 1]*/
RULE()(elems[iChild], elems[iChild + 1])
)
{
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
if (/*!(elems.back() < elems[iChild])*/
!RULE()(elems.back(), elems[iChild])
) break;//直接个最后一个节点比较
else elems[iFather] = elems[iChild];
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//4: 循环第二步,直到 没有子节点
elems[iFather] = elems.back();
elems.pop_back(); //最后,删除末尾节点
}
T& top() { return elems.front(); }//返回堆顶的元素
void Print(){
typename Container::iterator it;
for (it = elems.begin(); it != elems.end(); it++){
cout << *it << " ";
}
cout << endl;
}
};
//增加比较规则,使用 仿函数,作为一个模板类型
//支持函数指针的使用
template<typename T, typename Container = vector<T>, typename RULE = less<T>>
class MyPriQue
{
private:
RULE myRule; //定义私有成员来存储比较规则
//如果是仿函数 --》 生成一个默认的对象
//如果是函数指针--》 定义一个函数指针,构造的时候,函数指针赋值
Container elems; //使用 vector 来存储优先级队列中的数据
public:
MyPriQue(){}
MyPriQue(RULE rule) :myRule(rule){} //构造函数初始化比较规则
int size(){ return elems.size(); }
bool empty() { return elems.empty(); }
void push(T x) {
//1: 把新插入元素 x 放在最后面
elems.push_back(x); //或者 elems.resize(size()+1); 扩充一个元素
int iChild = size() - 1; //最后一个节点的下标
int iFather = (iChild - 1) / 2; //它的父节点下标
while (iChild > 0) //iChlid 是根节点了,就不要往上找了
{
//2:x 与 当前节点的父节点比较
if (/*elems[iFather] < x*/
myRule(elems[iFather], x)
) //构造堆使用的比较规则,比较规则改变了,则堆也改变了
{
//流程优化,不做交换,只是把父节点下移
//2 - 1:大于父节点,则 把父节点下移
elems[iChild] = elems[iFather];
}
else break;//2 - 2:小于等于父节点, 则 x 元素插入完成
//3: 循环执行:变量轮换,重新找父节点
iChild = iFather; //交换完成后,继续往上找父节点
iFather = (iChild - 1) / 2;
}//3:循环执行 第二步,直到x位于根节点
//循环完成后,iChild 位置,就是 x 这个值的需要保存的最终位置
elems[iChild] = x;
}
void pop()
{
//1: 交换 首尾 元素, 删除最后一个元素(最大的值)
//先不删除最后一个节点,用于暂存最终需要保存的元素
//处理完毕后,再删除
int iFather = 0; //这是需要调整的节点下标
int iChild = 1; //左子节点
while (iChild < size()) //存在子节点的情况才进行比较,无子节点就没有比较的必要了
{
//2: 调整堆:根节点元素 x 和 左右两个子节点中最大的 subMax 进行比较
//我们需要找左右两个子节点中最大的(右子节点有可能不存在)
if (iChild + 1 < size()
&& /*elems[iChild] < elems[iChild + 1]*/
myRule(elems[iChild], elems[iChild + 1])
)
{
//右子节点既存在,也大于左子节点,则子节点去右子节点
iChild++;
}
if (/*!(elems.back() < elems[iChild])*/
!myRule(elems.back(), elems[iChild])
) break;//直接个最后一个节点比较
else elems[iFather] = elems[iChild];
//3: 循环第二步,变量轮换,继续找下一个子节点
iFather = iChild;
iChild = 2 * iFather + 1; //左子节点
}//3: 循环第二步,直到 没有子节点
elems[iFather] = elems.back();
elems.pop_back();//最后,删除末尾节点
}
T& top() { return elems.front(); }//返回堆顶的元素
void Print(){
typename Container::iterator it;
for (it = elems.begin(); it != elems.end(); it++){
cout << *it << " ";
}
cout << endl;
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AAA
{
private:
int x;
int y;
public:
AAA() :x(0), y(0){}
AAA(int a, int b) :x(a), y(b){}
bool operator < (const AAA &A) const { return x < A.x;}
friend ostream& operator << (ostream& os, const AAA& A){
os << "(" << A.x << ", " << A.y << ")";
return os;
}
};
class MyRule
{
public:
bool operator ()(int x, int y) { return y < x; }
};
bool MyComp(int x, int y) { return y < x;}
void TestMyPriQue()
{
MyPriQue<int> iPriQue;
MyPriQue<string, deque<string>> sPriQue;
MyPriQue<int, vector<int>, MyRule> iPriQue2;
int arr[] = { 1, 3, 5, 2, 4, 6, 7, 8, 9 };
string sArr[] = { "AAA", "BBBB", "CC", "aa", "bbb", "cccc" };
cout << "iPriQue 入队列: ";
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
cout << arr[i] << " ";
iPriQue.push(arr[i]);
iPriQue2.push(arr[i]);
}
cout << endl;
cout << "sPriQue 入队列: ";
for (int i = 0; i < sizeof(sArr) / sizeof(sArr[0]); i++) {
cout << sArr[i] << " ";
sPriQue.push(sArr[i]);
}
cout << endl;
/*
cout << "大堆 : ";
iPriQue.Print();
sPriQue.Print();
cout << endl;
*/
cout << "iPriQue 出队列: ";
while (!iPriQue.empty()) {
cout << iPriQue.top() << " ";
iPriQue.pop();
}
cout << endl;
cout << "iPriQue2出队列: ";
while (!iPriQue2.empty()) {
cout << iPriQue2.top() << " ";
iPriQue2.pop();
}
cout << endl;
cout << "sPriQue 出队列: ";
while (!sPriQue.empty()) {
cout << sPriQue.top() << " ";
sPriQue.pop();
}
cout << endl;
cout << endl;
///*
//二进制“>”:“AAA”不定义该运算符或到预定义运算符可接收的类型的转换
MyPriQue<AAA> aPriQue;
AAA aArr[] = { AAA(1, 0), AAA(), AAA(0, 1), AAA(1, 2), AAA(1, 1) };
cout << "aPriQue入队列:";
for (int i = 0; i < sizeof(aArr) / sizeof(aArr[0]); i++) {
cout << aArr[i] << " ";
aPriQue.push(aArr[i]);
}
cout << endl;
cout << "aPriQue出队列:";
while (!aPriQue.empty()) {
cout << aPriQue.top() << " ";
aPriQue.pop();
}
cout << endl;
//*/
//没有这个构造函数
//MyPriQue_V4<int, vector<int>, bool(*)(int, int)> iPriQue3(MyComp);
MyPriQue<int, vector<int>, bool(*)(int, int)> iPriQue3(MyComp);
cout << "iPriQue3入队列: ";
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
cout << arr[i] << " ";
iPriQue3.push(arr[i]);
}
cout << endl;
cout << "iPriQue3入队列: ";
while (!iPriQue3.empty()) {
cout << iPriQue3.top() << " ";
iPriQue3.pop();
}
cout << endl;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//作业:
//定义 4 个优先级队列,存储string对象 {"AA", "BBBB", "CCC", "aaaa", "cc", "bbb"}
//要求:
//sPriQue1: 出队列的时候,按照字符串 ASCII 降序排列
//sPriQue2: 出队列的时候,按照字符串 ASCII 升序排列
//sPriQue3: 出队列的时候,按照字符串长度 升序排列(长度一样再比较 ASCII 升序)
//sPriQue4: 出队列的时候,按照字符串长度 降序排列(长度一样再比较 ASCII 降序)
class MyRuleS_2
{
public:
bool operator ()(const string& s1, const string& s2) const
{ return s2 < s1; }
};
class MyRuleS_3
{
public:
bool operator ()(const string& s1, const string& s2) const{
if (s1.length() == s2.length()) { return s2 < s1; }
else { return s2.length() < s1.length(); }
}
};
class MyRuleS_4
{
public:
bool operator ()(const string& s1, const string& s2) const {
if (s1.length() == s2.length())
return s1 < s2;
else
return s1.length() < s2.length();
}
};
void HomeWork()
{
string sArr[] = { "AA", "BBBB", "CCC", "aaaa", "cc", "bbb" };
MyPriQue_V4<string> sPriQue1;
MyPriQue_V4<string, vector<string>, MyRuleS_2> sPriQue2;
MyPriQue_V4<string, vector<string>, MyRuleS_3> sPriQue3;
MyPriQue_V4<string, vector<string>, MyRuleS_4> sPriQue4;
for (int i = 0; i < sizeof(sArr) / sizeof(sArr[0]); i++) {
sPriQue1.push(sArr[i]);
sPriQue2.push(sArr[i]);
sPriQue3.push(sArr[i]);
sPriQue4.push(sArr[i]);
}
cout << "sPriQue1:";
while (!sPriQue1.empty()) {
cout << sPriQue1.top() << " ";
sPriQue1.pop();
}
cout << endl;
cout << "sPriQue2:";
while (!sPriQue2.empty()) {
cout << sPriQue2.top() << " ";
sPriQue2.pop();
}
cout << endl;
cout << "sPriQue3:";
while (!sPriQue3.empty()) {
cout << sPriQue3.top() << " ";
sPriQue3.pop();
}
cout << endl;
cout << "sPriQue4:";
while (!sPriQue4.empty()) {
cout << sPriQue4.top() << " ";
sPriQue4.pop();
}
cout << endl;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//堆排序的实现:实现升序排列
//第一步:把序列构造成大堆
// 从最后一个父节点开始,做调整,把这个父节点看成子树的根节点,这个子树调整成大堆
// 依次往上,知道把根节点调整完毕
//第二步:从最后一个节点开始首位交换,调整堆 (排除最后的节点)
// 直到 堆 只剩一个元素
//作业,完成下面两个函数 HeapSort 实现对 arr 数组的堆排序
void HeapFixDown(int arr[], int iSize, int iPos)
{
//把 arr 数组的 iPos 位置元素下沉,确保iPos 节点往下,都是大堆
//最多下沉到 iSize位置
int iFather = iPos;
int iChild = iPos * 2 + 1; //左子节点
int iTmp = arr[iPos]; //待寻找位置的值
while (iChild < iSize) {
//右子节点是否存在,右子节点是否大于左子节点
if (iChild + 1 < iSize && arr[iChild] < arr[iChild + 1]) {
iChild++; //取右子节点进行交换 (最大的子节点)
}
//优化方案:所谓的交换,只需要把最大的子节点上移
// 最终位置,保存 arr[iPos]
if (iTmp < arr[iChild])
arr[iFather] = arr[iChild];
else break;
//变量置换,继续找下一个最大的子节点
iFather = iChild;
iChild = 2 * iFather + 1;
}
//最后,无论是break ,还是 (iChild < iSize) 为false
//iFather 的位置就是 arr[iPos] 应该保存的位置
arr[iFather] = iTmp;
}
void HeapSort(int arr[], int iSize)
{
//从最后一个父节点开始,调用 HeapFixDown
//从最后一个节点开始,交换到根节点,并 调用 HeapFixDown下沉根节点
//数组堆化: 从最后一个父节点开始,到根节点结束,一次把这个子树,做下沉操作
//最后一个父节点 --- 最后一个节点的父节点
// size - 1 ---> (size-1-1)/2 = size/2 - 1
for (int i = iSize / 2 - 1; i >= 0; i--)
HeapFixDown(arr, iSize, i);
//--> arr 变成大堆的形式
//堆排序:
//1: 把最大的交换到末尾
//2: 根节点下沉
//3: 末尾位置前移,循环
for (int i = iSize - 1; i > 0; i--){
std::swap(arr[0], arr[i]); //交换首尾
HeapFixDown(arr, i, 0);//把根节点,下沉到 i - 1 位置
}
//HeapFixDown 时间复杂度 O(log(N))
//所以 HeapSort 的时间复杂度是 O(N*log(N))
//冒泡,选择 --》时间复杂度是 O(N^2)
}
//留一个问题: 怎么修改这个函数,使它支持升序,降序,或者自定义排序?
void TestHeapSort()
{
int arr[] = { 1, 4, 7, 8, 5, 3, 2, 6, 9 };
HeapSort(arr, sizeof(arr) / sizeof(arr[0]));
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main()
{
//TestMyPriQue();
//HomeWork();
TestHeapSort();
system("pause");
return 0;
}
C++学习笔记_21 优先级队列实现-堆积树-堆排序 2021-05-24
猜你喜欢
转载自blog.csdn.net/lybc2019/article/details/117225227
今日推荐
周排行