堆排序

一、基础堆的搭建,shift Down/shift Up函数,逐个插入元素,或者直接插入数组、终端中以树形结构方式的打印函数的实现

template 
class MaxHeap
{
private:
	Item* data;
	//堆中已经存放了多少堆元素
	int count;
	//可以存放多少个堆元素
	int capacity;
	//私有属性,对象调用不了,用户调用Insert函数就可以了
	void shiftUp(int k)
	{
		while (k>1&&data[k] > data[k / 2])
		{
			swap(data[k], data[k / 2]);
			k /= 2;
		}
	}
	//如果有左右孩子,则找出左右孩子的最大值索引,跟父节点比较,如果父节点比他们大,则跳出,反之则交换
	void shiftDown(int k)
	{
		while (2 * k <= count)
		{
			//j存放孩子的最大值索引,默认为左孩子
			int j = 2 * k;
			//要考虑j边界问题
			if (j + 1 <= count && data[j + 1] > data[j])
			{
				j += 1;
			}
			if (data[k] >= data[j])
				break;
			swap(data[k], data[j]);
			k = j;
		}


	}
	//在控制台中打印树型辅助函数
	void putNumberInLine(int num, string &line, int index_cur_level, int cur_tree_width, bool isLeft) {

		int sub_tree_width = (cur_tree_width - 1) / 2;
		int offset = index_cur_level * (cur_tree_width + 1) + sub_tree_width;
		assert(offset + 1 < line.size());
		if (num >= 10) {
			line[offset + 0] = '0' + num / 10;
			line[offset + 1] = '0' + num % 10;
		}
		else {
			if (isLeft)
				line[offset + 0] = '0' + num;
			else
				line[offset + 1] = '0' + num;
		}
	}
	//在控制台中打印树型辅助函数
	void putBranchInLine(string &line, int index_cur_level, int cur_tree_width) {

		int sub_tree_width = (cur_tree_width - 1) / 2;
		int sub_sub_tree_width = (sub_tree_width - 1) / 2;
		int offset_left = index_cur_level * (cur_tree_width + 1) + sub_sub_tree_width;
		assert(offset_left + 1 < line.size());
		int offset_right = index_cur_level * (cur_tree_width + 1) + sub_tree_width + 1 + sub_sub_tree_width;
		assert(offset_right < line.size());

		line[offset_left + 1] = '/';
		line[offset_right + 0] = '\\';
	}
public:
	MaxHeap(int capacity)
	{
		//因为堆的根节点索引从1开始
		data = new Item[capacity+1];
		count = 0;
		this->capacity = capacity;
	}
	//heapify的过程,算法复杂度为O(n),将n个元素逐个插到一个空堆中,算法复杂度是O(nlogn)
	MaxHeap(Item arr[],int n)
	{
		data = new Item[n + 1];
		for (int i = 0; i < n; i++)
		{
			data[i + 1] = arr[i];
		}
		count = n;
		capacity = n;
		for (int i = count / 2; i >= 1; i--)
			shiftDown(i);
	
	}
	~MaxHeap()
	{
		delete[] data;
	}
	int size()
	{
		return count;
	}
	bool isEmpty()
	{
		return count == 0;
	}
	//给堆插入元素
	void Insert(Item item)
	{
		assert(count + 1 <= capacity);
		data[count + 1] = item;
		count++;
		shiftUp(count);
	}
	//从堆中提取元素,数组中堆以外的元素不是为空,而是有值得数,是从根节点替换下来的
	Item extractMax() 
	{
		assert(count >=1);
		Item pop = data[1];
		
		swap(data[1], data[count]);
		count--;
		shiftDown(1);
		
		return pop;

	}
	//在控制台中打印树型函数
	void testPrint() {

		if (size() >= 100) {
			cout << "Fancy print can only work for less than 100 int";
			return;
		}

		if (typeid(Item) != typeid(int)) {
			cout << "Fancy print can only work for int item";
			return;
		}

		cout << "The Heap size is: " << size() << endl;
		cout << "data in heap: ";
		for (int i = 1; i <= size(); i++)
			cout << data[i] << " ";
		cout << endl;
		cout << endl;

		int n = size();
		int max_level = 0;
		int number_per_level = 1;
		while (n > 0) {
			max_level += 1;
			n -= number_per_level;
			number_per_level *= 2;
		}

		int max_level_number = int(pow(2, max_level - 1));
		int cur_tree_max_level_number = max_level_number;
		int index = 1;
		for (int level = 0; level < max_level; level++) {
			string line1 = string(max_level_number * 3 - 1, ' ');

			int cur_level_number = min(count - int(pow(2, level)) + 1, int(pow(2, level)));
			bool isLeft = true;
			for (int index_cur_level = 0; index_cur_level < cur_level_number; index++, index_cur_level++) {
				putNumberInLine(data[index], line1, index_cur_level, cur_tree_max_level_number * 3 - 1, isLeft);
				isLeft = !isLeft;
			}
			cout << line1 << endl;

			if (level == max_level - 1)
				break;

			string line2 = string(max_level_number * 3 - 1, ' ');
			for (int index_cur_level = 0; index_cur_level < cur_level_number; index_cur_level++)
				putBranchInLine(line2, index_cur_level, cur_tree_max_level_number * 3 - 1);
			cout << line2 << endl;

			cur_tree_max_level_number /= 2;
		}
	}
};
template
void heapsort(T arr[],int n)
{
	MaxHeap maxheap = MaxHeap(arr, n);
	for (int i = n - 1; i >= 0; i--)
	{
		arr[i] = maxheap.extractMax();
	}
}

shiftDown传统的比较三个值大小的写法

	void shiftDown(int k)
	{
		if (2 * k <= count)
		{
			Item max = data[k];
			Item maxindex = k;
			if (data[2 * k] > max)
			{
				max = data[2 * k];
				maxindex = 2 * k;
			}
			//注意j的边界取值
			if (data[2 * k + 1] > max && 2 * k + 1 <= count)
			{
				max = data[2 * k + 1];
				maxindex = 2 * k + 1;
			}

			//如果父节点比子节点大则不需要交换
			if (max != data[k])
			{
				swap(data[k], data[maxindex]);
				shiftDown(maxindex);
			}
		}
	}

 

你可能感兴趣的:(C++,algorithm)