这里只说一点,根据一个大小为n的数组,然后进行批量的建堆;其用的是Floyd算法,它首先在LastInetral_node=(n-2)>>1;
然后依次遍历其内点,然后进行下滤算法:(图借用邓俊辉的数据结构)
可以看出,其时间复杂度为:一颗n个节点的完全二叉树,其内部节点为K= n/2 - 1 ;
从而就需要进行 ;
当然还有另一种蛮力算法,就是每次将元素插入堆的末尾,然后进行上滤;
明显时间复杂度为:,越靠近底层,节点越多深度越深;并且在这么长的时间下,我们用AVL树,本可以做到全序,且时间复杂度也为,从而肯定有更好的办法,如Floyd算法;
堆排序的时间复杂度:因为就是先对数组进行建堆,然后每次都delete Max,即取出第一个元素,将其赋值给array[hi--];
建堆需要上面的Floyd算法;即;然后再进行依次的删除操作,也就时间,所以总时间就是,当然可能额外的空间可以优化为;我写的算法里并没有;
但书中给出了解释:
即它使用原数组进行建堆,然后从头开始遍历,将每一步的根m(最大元素)与末尾(hi--)x交换,然后将x进行下滤,从而每一步下滤时间都不超过,因为需要迭代n次,从而总时间是;且辅助空间仅是swap的;
但我的算法,是在堆中重新用了一个数组,从而辅助空间不能减少,但是时间复杂度为,额外空间复杂度为;
下面贴出我的堆的数据结构,当然不是优化版本,因为每一次插入操作,都需要复制一遍数组,我其实可以继承vector的;
template <typename T>
class PQ
{
public:
int size;
PQ(int n=0) :size(n) {
PQ_arr = new T[n];
};
//拷贝构造
PQ(PQ &it)
{
size = it.size;
delete PQ_arr;
PQ_arr=new T[size];
for (int i = 0; i < size; ++i)
{
PQ_arr[i] = it.value[i];
}
}
PQ(const vector<T> &vec,int n):size(vec.size()) {
PQ_arr = new T[size];
int i = 0;
for (auto it : vec)
{
PQ_arr[i++] = it;
}
heapify(n);
};
//复制构造
PQ &operator=(const PQ &it)
{
size = it.size;
delete []PQ_arr;
PQ_arr = new T[size];
for (int i = 0; i < size; ++i)
{
PQ_arr[i] = it.value[i];
}
return *this;
}
T &value(int i)
{
return PQ_arr[i];
}
T &value(int i) const
{
return PQ_arr[i];
}
/*! overload stream operator << */
friend std::ostream & operator << (std::ostream & os, const PQ & _Q)
{
for (int i=0;i< _Q.size;++i)
{
os << _Q.value(i) << " ";
}
return os;
};
void insert(T);
T getMax();
T delMax();
~PQ()
{
delete []PQ_arr;
}
private:
void percolateDown(int n, int i); //下滤
void percolateUp(int i); //上滤
void heapify(int n);
T* PQ_arr;
};
template <typename T>
T PQ<T>::getMax()
{
return PQ_arr[0];
}
template <typename T>
void PQ<T>::insert(T e)
{
//就这么慢吧,可以用vector来实现
T *temp = new T[size + 1];
for (int i = 0; i < size; ++i)
{
temp[i] = PQ_arr[i];
}
delete PQ_arr;
temp[size] = e;
PQ_arr = temp;
size++;
percolateUp(size-1);
}
template <typename T>
void PQ<T>::percolateUp(int i)
{
while ((i - 1) >= 0)
{
int parent = (i - 1) >> 1;
if (PQ_arr[i] > PQ_arr[parent]) std::swap(PQ_arr[i], PQ_arr[parent]);
else break;
i = parent;
}
}
template <typename T>
void PQ<T>::percolateDown(int n, int i)
{
T old = PQ_arr[i];
int __chlid = i;
while (true)
{
if (((i << 1) + 1 < n) && old < PQ_arr[(i << 1) + 1]) __chlid = (i << 1) + 1;
if (((i << 1) + 2 < n) && PQ_arr[__chlid] < PQ_arr[(i << 1) + 2]) __chlid = (i << 1) + 2;
if (__chlid == i) break;
PQ_arr[i] = PQ_arr[__chlid];
i = __chlid;
}
PQ_arr[i] = old;
}
template <typename T>
T PQ<T>::delMax()
{
std::swap(PQ_arr[0], PQ_arr[size-1]);
percolateDown(size - 1, 0);
--size;
return PQ_arr[size ];
}
template <typename T>
void PQ<T>::heapify(int n)
{
int j = (n - 2) >> 1;
for (int i = j; i >= 0; --i)
{
percolateDown(n,i);
}
}
void Heap_sort(vector<int> &arr)
{
//先进行一次堆操作
if (arr.size() == 1) return;
PQ<int> heap_(arr, arr.size());
int hi = arr.size() - 1;
while (hi>=0)
{
int max = heap_.delMax();
arr[hi--] = max;
}
}
int main()
{
vector<int> iyu = { 0,3,1,5,4,2 };
PQ<int> heap_my(iyu, iyu.size());
std::cout << heap_my << endl;
heap_my.insert(7);
std::cout << heap_my << endl;
int var=heap_my.delMax();
std::cout << var<< endl;
std::cout << heap_my << endl;
Heap_sort(iyu);
return 0;
}