堆排序与优先队列(c++实现版)

形成堆:
首先形成堆,我们有两种处理(“上浮”和”下沉”)
上浮:在原堆尾添加元素时,通过比较添加元素和原堆(二叉树)中父节点关系,决定是否继续上浮
下沉:在原堆首添加元素时(此时添加元素是二叉树的根节点),通过比较父节点与左右节点,找出最大的节点,通过是否交换元素,判断是否需要继续下沉
上浮和下沉最坏情况都是lgn,其实就是和二叉树树高有关 T(n) = O(lgn)
总结:两种方法都能形成堆,可是两种方法都有不同使用场景才能发挥其最大威力,
比如:如果向堆集合中添加元素,对于一个序列我们习惯都是在尾部添加(数组,向量(Vector)都是这样),如果我们执意从序列首部添加元素,那未免不得承担将原序列向后挪的性能损失了(因为这是可以避免的,所以我不得不称它为一种”性能损失了”)
所以向原堆添加元素有两种做法:
1.将添加元素放在原堆尾部,采用上浮的做法重新生成堆
2.将添加元素放在原堆首部,采用下沉的做法重新生成堆(其实我上面说有性能损失其实是有问题的,因为计算机中表示序列的一般只有两种
1.顺序存储(数组之流)
2.链式存储(链表之流)
因此上种说法对于链式存储就不适用了(因为添加首元素只需修改指针就可以),此外我下面写的堆排序中是顺序存储结构采用下沉的做法生成堆,因为这种业务不需要挪,所以当我们把添加元素弄到首元素时没有不必要的性能损失时,就是它大放异彩的时候
知道如何形成堆,那么堆排序和优先队列也就不难了
堆排序:

我们首先将输入序列S,通过对所有父节点下沉操作形成堆(因为顺序存储的序列已经给定了,(下沉和上浮性能都无异了)
然后通过将堆的首元素与尾部元素交换,从首元素到新堆尾部元素(上次的堆尾部元素位置 - 1)产生新堆,以此类推,直到无新堆产生
通过操作最大或最小堆获得非递减或非递增序列
性能1.:对于序列大小为n,形成堆时间为O(n * lgn),这个上界不是很紧,读者可以运用自己的聪明才智(一丝丝数学知识)让其紧到O(n)
2.迭代产生新堆:第一步都没紧,我第二步不紧也是O(n * lgn)
综上可知,堆排序最坏情况下T(n) = O(n * lgn)

优先队列:
序列我采用的是顺序存储,每次Insert操作就是上浮的时间(O(lgn)),其他的就没什么可说的了,有说的我会来更

Priority_Queue.h

#pragma once
#include <vector>
#include <iostream>

template<typename V>
class Priority_Queue {
public:
    Priority_Queue() = default;
    ~Priority_Queue() = default;
    Priority_Queue(const std::vector<V>& v);
private:
    std::vector<V> vec;
public:
    void Insert(const V& v);
    V Maximum();
    void Print();
    //V Extract_Max();
private:
    void swim(const int& k) {
        int largest = k;
        while ((largest - 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值