我创建了一个Heap的数据结构,而不是像STL那样使用函数解决堆排序,当然STL的比较优雅一点,我只是提供第二个思路
#ifndef HEAP_SORT_H
#define HEAP_SORT_H
#include <vector>
#include <cstddef>
#include <iterator>
#ifdef _DEBUG
#include <iostream>
#endif // _DEBUG
template <typename T>
struct less {
bool operator() (const T& lhs, const T& rhs)
{
return lhs < rhs;
}
};
//
// 最大堆,用于实现堆排序
// 算法思路:
// 利用堆这种数据结构的特性,实现排序
// 在这里的思路是Heap含有一个vec,并没有事实能够证明继承比包含好用
//
template <typename T, typename Container = std::vector<T>, typename Compare = less<T> >
class MaxHeap {
public:
typedef size_t pos_type;
typedef size_t size_type;
typedef ptrdiff_t diff_type;
public:
template <typename Iterator>
MaxHeap(Iterator first, Iterator last) : vec(first, last), comp(Compare())
{
this->build_max_heap();
#ifdef _AL_DEBUG
// Show the original squence
for (; first != last; ++first)
{
std::cout << *first << " ";
}
std::cout << std::endl;
// Show the squence after build_max_heap()
for (std::vector<T>::iterator iter = vec.begin();
iter != vec.end(); ++iter)
{
std::cout << *iter << " ";
}
std::cout << std::endl;
#endif // _AL_DEBUG
}
virtual ~MaxHeap() { }
inline size_type size() const
{
return (size_type) this->vec.size();
}
inline size_type capacity() const
{
return (size_type) this->vec.capacity();
}
inline const T& top() const
{
return this->first();
}
inline bool pop()
{
if (size() == 0) return false;
this->swap(1, size());
// delete begin in vec
this->vec.pop_back();
// do max heapify
this->max_heapify(_START_POS);
// test the size of vec
return true;
}
inline void push(const T& new_val)
{
this->vec.push_back(new_val);
this->update_heapify(this->size());
}
protected:
Container vec;
Compare comp;
protected:
inline pos_type parent(pos_type i) const
{
return i >> 1;
}
inline pos_type right(pos_type i) const
{
return (i << 1) + 1;
}
inline pos_type left(pos_type i) const
{
return i << 1;
}
inline bool has_left(pos_type i) const
{
if (left(i) > size() || left(i) < _START_POS) return false;
else return true;
}
inline bool has_right(pos_type i) const
{
if (right(i) > size() || right(i) < _START_POS) return false;
else return true;
}
inline bool has_parent(pos_type i) const
{
if (parent(i) < _START_POS) return false;
else return true;
}
inline const T& value(pos_type i) const
{
return vec[--i];
}
inline const T& first() const
{
return vec[0];
}
inline void swap(pos_type lhs, pos_type rhs)
{
--lhs, --rhs;
Container::iterator left = this->vec.begin() + lhs;
Container::iterator right = this->vec.begin() + rhs;
T tmp = *left;
*left = *right;
*right = tmp;
}
// 建堆操作,时间复杂度:O(n)
void build_max_heap()
{
pos_type last_pos = vec.size();
#ifdef _AL_DEBUG
std::cout << "Size: " << last_pos << std::endl;
#endif // _AL_DEBUG
if (has_parent(last_pos))
{
for (pos_type p = parent(last_pos); p != 0; --p)
{
max_heapify(p);
}
}
}
// 保持堆性质操作,时间复杂度:O(lgn)
void max_heapify(pos_type pos)
{
pos_type max_pos = pos;
pos_type left_pos = left(pos);
pos_type right_pos = right(pos);
#ifdef _AL_DEBUG
std::cout << "max_heapify " << pos << " " << left_pos
<< " " << right_pos << " ";
std::cout << "max_heapify " << value(pos) << " ";
#endif // _AL_DEBUG
// Do exchange among this 3 nodes
// and record the max one to max_pos
// or the value of max_pos will not
// be changed
if (has_left(pos) && comp(value(max_pos), value(left_pos)))
{
max_pos = left_pos;
#ifdef _AL_DEBUG
std::cout << value(left_pos) << " ";
#endif // _AL_DEBUG
}
if (has_right(pos) && comp(value(max_pos), value(right_pos)))
{
max_pos = right_pos;
#ifdef _AL_DEBUG
std::cout << value(right_pos);
#endif // _AL_DEBUG
}
#ifdef _AL_DEBUG
std::cout << std::endl;
#endif // _AL_DEBUG
if (max_pos != pos)
{
swap(max_pos, pos);
max_heapify(max_pos);
}
}
void update_heapify(pos_type p)
{
pos_type cur = p;
pos_type parent_pos = parent(cur);
while (has_parent(cur))
{
#ifdef _AL_DEBUG
// Show the squence after build_max_heap()
for (std::vector<T>::iterator iter = vec.begin();
iter != vec.end(); ++iter)
{
std::cout << *iter << " ";
}
std::cout << std::endl;
#endif // _AL_DEBUG
if (comp(value(parent_pos), value(cur)))
{
swap(parent_pos, cur);
cur = parent_pos;
parent_pos = parent(cur);
}else break;
}
}
static const size_type _START_POS = 1;
};
template <typename Iterator>
void heap_sort(Iterator first, Iterator last)
{
_heap_sort_aux(first, last, std::_Val_type(first));
}
//
// 因为借助vector实现的,而不是自己利用allocator实现的,所以没办法控制
// heap-sort过程中将最大值放在末尾的步骤,所以只能将最大值赋给当前的指针
// 指向的位置
//
template <typename Iterator, typename Val>
void _heap_sort_aux(Iterator first, Iterator last, Val*)
{
MaxHeap<Val> heap(first, last);
for (; first != last && heap.size() != 0; ++first)
{
*first = heap.top();
heap.pop();
}
}
#endif