- 建堆【以大顶堆为例】
- 排序
性能
- 建堆的时间复杂度为O(N)
- heapify复杂度O(logN)
- 堆排序对N个数进行heapify
堆排序的时间复杂度:O(NlogN)
为何堆排序是不稳定排序?
当数组中有相等元素时,堆排序算法对这些元素的处理方法不止一种,故是不稳定的。
实现
//heapSort.cc
#include "heapSort.h"
void heapify(vector<int>& nums, int pos, int len) {
int parent = pos;
int son = 2 * pos + 1; //son表示挑战的孩子的下标
//2N+1是左子节点的下标
while(son < len) {
if(son + 1 < len && nums[son] < nums[son + 1]) {
//右结点存在,且强于左节点
//先和兄弟比
son = son + 1;
}
if(nums[son] > nums[parent]) {
//在和父亲比
std::swap(nums[son], nums[parent]);
//父亲被替换到新的位置,向下继续循环
parent = son;
son = 2 * parent + 1;
}
else {
//如果不交换,循环终止
break;
}
}
}
void heap_sort(vector<int>& nums) {
//建堆
//最后一个父结点下标是N/2-1
for(int i = nums.size() / 2 - 1; i >= 0; i--) {
//i表示起点的下标,从最后一个父结点到根节点
heapify(nums, i, nums.size());
}
std::swap(nums[0], nums[nums.size() - 1]);
//交换根节点(最大值)和最后一个结点的位置,并把堆大小减1
//排序
for(int len = nums.size() - 1; len > 0; len--) {
//i表示堆的规模
heapify(nums, 0, len);
std::swap(nums[0], nums[len - 1]);
}
}
//heapSort.h
#ifndef __HEAP_SORT_H_
#define __HEAP_SORT_H_
#include <vector>
#include <algorithm>
using std::vector;
//大根法的树
//满足两个性质:
//1. 满足完全二叉树
//2. 父结点比子结点大,根结点最大
//pos指向子树调整的起点的下标,起点编号是pos+1
//左孩子下标2*pos+1,编号2*pos+2
//右孩子下标2*pos+2,编号2*pos+3
//堆最后一个元素的编号len, 下标len-1
//
void heapify(vector<int>& nums, int pos, int len);
void heap_sort(vector<int>& nums);
#endif //end of __HEAP_SORT_H__
//main.cc
#include <iostream>
#include "selectSort.h"
#include <cstdlib>
#include <ctime>
#include "heapSort.h"
using std::cout;
using std::endl;
const size_t nums_len = 10;
void print(vector<int>& nums) {
for(auto i : nums) {
cout << i << ' ';
}
cout << endl;
}
void test() {
//创建测试数据
std::srand(std::time(nullptr));
vector<int> nums;
for(int i = 0; i < nums_len; ++i) {
nums.push_back(std::rand() % 99);
}
print(nums);
//select_sort(nums);
heap_sort(nums);
print(nums);
}
int main(void)
{
test();
}
swap函数的使用
Before C++11, this function was defined in header .
// swap algorithm example (C++11)
#include <iostream> // std::cout
#include <utility> // std::swap
int main () {
int x=10, y=20; // x:10 y:20
std::swap(x,y); // x:20 y:10
int foo[4]; // foo: ? ? ? ?
int bar[] = {10,20,30,40}; // foo: ? ? ? ? bar: 10 20 30 40
std::swap(foo,bar); // foo: 10 20 30 40 bar: ? ? ? ?
std::cout << "foo contains:";
for (int i: foo) std::cout << ' ' << i;
std::cout << '\n';
return 0;
}