堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。因此分为大根堆与小跟堆。
非叶子节点值大于等于左右子节点值: &&

非叶子节点值小于等于左右子节点值: &&

思路:
1、构造n个数值的大根堆或小根堆
2、将堆顶(最大或最小值),放至堆尾
3、继续构造前n-1个数值,n = n-1 转1,如此循环
4、输出 升序或降序 序列
1、从非叶子节点开始调整 n/2
2、在第2i个节点和第2i+1个节点中(左右节点)选最大值为X
3、若第i个节点(根)小于X则二者交换
4、交换后还需考虑以2i为根或2i+1为根的子树是否仍是堆,如不是则需要继续向下调整。
5、 1~4 循环至堆顶为最大值
6、堆顶堆尾交换元素,最大值放置最后。前 n - 1 继续调整,转 1; n == 0 结束

注:图像不清晰,资源有上传视频:堆排序-CSDN直播
- #include
- #include
- #include
-
-
- using namespace std;
-
- //<:升序,大根堆, >:降序,小根堆
- #define cmp <
- typedef int Node;
-
- void printHeap(vector<int>& heap){
- for(auto i: heap){
- cout << i << " ";
- }
- cout << endl;
- }
-
- void nodeAdjust(vector
& tree, Node root, int size) { - int swapNode = root;
- //左右节点
- Node leftNode = root * 2 + 1;
- Node rightNode = root * 2 + 2;
-
- //叶子节点无需调整
- if(root > size/2-1 ) return;
-
- //左右节点与根结点进行比较,找极大或极小值
- if(leftNode < size && tree[swapNode] cmp tree[leftNode])
- swapNode = leftNode;
- if(rightNode < size && tree[swapNode] cmp tree[rightNode])
- swapNode = rightNode;
-
- if( tree[root] cmp tree[swapNode] ){
- //交换节点
- swap(tree[root], tree[swapNode]);
-
- //子节点被调整,则对应的子树堆被破坏需要重新调整
- nodeAdjust(tree, swapNode, size);
- }
- }
-
- //对于每个非叶子节点都进行调整,从后往前
- void heapAdjust(vector
& tree, int size) { - for(int i = size/2-1; i >= 0; i --){
- nodeAdjust(tree, i, size);
- }
- }
-
- void heapSort(vector<int>& heap, int size){
- for(int i = 0; i < size; i++){
- //调整堆
- heapAdjust(heap, size - i);
- //将极值放最后
- swap(heap[0], heap[size - 1 - i ]);
- }
- }
-
- int main(){
- vector<int> tree = {2, 4, 1, 3, 6};
- heapSort(tree, tree.size());
- printHeap(tree);
- }