【算法导论】堆排序实现

我创建了一个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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值