常用排序算法之——堆排序

堆与堆排序的原理,参考该博客: 白话经典算法系列之七 堆与堆排序

 

二叉堆是个完全二叉树,可以用一个数组来保存节点,不会浪费空间,能快速定位;本人用一个vector来代替数组,省去自己对内存的分配/重分配和释放等操作。

 

堆排序就是每次取出小顶堆的堆顶并输出,然后对堆重新调整。

 

堆排序需要对数组先建堆【时间复杂度为O(N):高度为h的层最多有n/2h+1个结点,每个结点上调的复杂度为O(h),求累加和,取极限值,求出复杂度为O(3N)】,调整的过程中会打破元素的相对顺序,是一种不稳定的排序算法。时间复杂度最好、最坏、平均都为O(N logN)。

 

本人实现的代码,一个小顶堆,作为笔记:

#include <iostream> #include <cstring> #include <vector>

using namespace std; template<class T>

class MyHeap { public: // MyHeap() //默认构造函数对vector初始化

    // ~MyHeap()

    void init(T nums[], int n);  //用一个数组来初始化,并建好堆     int  size();           //返回堆中元素个数     void add(T new_item);  //添加一个元素     T    top();        //返回堆顶(最小值)     void pop();        //删除堆顶,不返回 

private: inline void fixUp(int i);   //堆的向上调整     inline void fixDown(int i);  //堆的向下调整  vector<T> m_tv; //采用vector数据结构来保存元素 }; template<class T>

void MyHeap<T>::init(T nums[], int n) { m_tv.resize(n); memcpy(&m_tv[0], nums, n * sizeof(T)); if(n < 2) { return; } for(int i = (n - 2) >> 1; i >= 0; --i)  //从第一个非叶节点开始向下调整  { fixDown(i); } } template<class T>

int MyHeap<T>::size() { return m_tv.size(); } template<class T>

void MyHeap<T>::add(T new_item) { m_tv.push_back(new_item); fixUp(m_tv.size() - 1);  //添加到数组尾部,然后向上调整 } template<class T> T MyHeap<T>::top() { if(m_tv.empty()) { cout << "head empty" << endl; return -1; } return m_tv[0];  //返回堆顶 } template<class T>

void MyHeap<T>::pop() { if( m_tv.empty() ) { return; } m_tv[0] = m_tv.back();  //将最后一个元素与堆顶交换,然后删除最后一个元素(变相删除第一个元素)  m_tv.pop_back(); fixDown(0);      //从堆顶开始向下调整 } template<class T> inline void MyHeap<T>::fixUp(int i) { //从叶子到根节点的路径上,把叶子调整到大于它的元素之上     for(int j = (i-1) >> 1; (j >= 0) && (i != 0) && (m_tv[j] > m_tv[i]); i = j, j = (i-1) >> 1) swap(m_tv[i], m_tv[j]); } template<class T> inline void MyHeap<T>::fixDown(int i) { const int n = m_tv.size(); int j = 2 * i + 1; while(j < n) { if(j+1 < n && m_tv[j+1] < m_tv[j])  //找出两个儿子中的较小值  { ++j; } if(m_tv[i] < m_tv[j])  //如果小于儿子的值,说明已经在合适的位置  { break; } swap(m_tv[i], m_tv[j]);  //和小儿子交换,直至找到比他大的儿子或者成为叶节点         i = j; j = 2 * i + 1; } } int main(int argc, char *argv[]) { int    ia[] = {4, 2, 1, 10, 3, 8}; double da[] = {4.13, 2.11, 1.1, 10.19, 3.12, 8.17}; MyHeap<int> ih;    //int元素的堆     MyHeap<double> dh;  //double元素的堆  ih.init(ia, sizeof(ia)/sizeof(*ia)); ih.add(5); const int in = ih.size(); cout << in << endl; for(int i = 0; i < in; ++i) { cout << ih.top() << ' '; ih.pop(); } cout << endl; dh.init(da, sizeof(da)/sizeof(*da)); dh.add(5.14); dh.add(7.16); const int dn = dh.size(); cout << dn << endl; for(int i = 0; i < dn; ++i) { cout << dh.top() << ' '; dh.pop(); } cout << endl; return 0; }

 

你可能感兴趣的:(排序算法)