堆排序

堆排序:

1.建大堆;

2.堆顶元素和堆最后一个元素交换;

3.继续建大堆(从上往下调整);

4.再取堆顶元素与堆尾倒数第二个元素交换;

5.升序输出

代码:

#pragma once

#include<iostream>
#include<vector>
//using namespace std;  //尽量不要让 using出现在头文件中 


template<class T>
class Heap
{
public:
	//构造
	Heap();

	//建大堆
	Heap(const T* a,size_t size);

	//堆排序
	void HeapSort();
	
	//建堆副
	void _Heap(const T* a,size_t size);

	//虚向下调整 实向上走
	void AdjustDown(int index,int num);

	void AdjustUp(int index);

	//打印
	void Print();

private:
	vector<T> MinHeap;
};

template<class T>
Heap<T>::Heap()
	{}

template<class T>
Heap<T>::Heap(const T* a,size_t size)
{
	_Heap(a,size);
}

template<class T>
void Heap<T>::_Heap(const T *a, size_t size)
{
	for(int i = 0; i < size; i++)
	{
		MinHeap.push_back(a[i]);
	}
	
	//第一个非叶子结点开始
	for(int i = (MinHeap.size()-2)/2; i >= 0; i--)
	{
		AdjustUp(i);
	}
}

template<class T>
void Heap<T>::AdjustDown(int index,int num)
{
	int child = 2*index+1;
	int cout = num+1;
	while(child < MinHeap.size()-cout)
	{
		if(child+1 <MinHeap.size()-cout && MinHeap[child] < MinHeap[child+1])
		{
			child++;
		}

		if(MinHeap[child] > MinHeap[(child-1)/2])
		{
			swap(MinHeap[child],MinHeap[(child-1)/2]);
			index = child; //交换后的是不是打乱了顺序  继续
			child = 2*index+1;//等效循环外的第一个条件
		}
		else
		{
			break;	
		}
	}
}

template<class T>
void Heap<T>::AdjustUp(int index)
{
	int child = index*2 + 1;
	while(child < MinHeap.size())
	{
		if((child+1)< MinHeap.size() && MinHeap[child+1] > MinHeap[child])
		{
			child++;
		}

		if(MinHeap[child] > MinHeap[(child-1)/2])
		{
			swap(MinHeap[child],MinHeap[(child-1)/2]);
			index = child;
			child = 2*index+1;
		}
		else
		{
			break;
		}
	}
}

template<class T>
void Heap<T>::HeapSort()
{
	for(int i = 0; i < MinHeap.size(); i++)
	{
		int num = MinHeap.size()-i-1;
		swap(MinHeap[0],MinHeap[num]);
		AdjustDown(0,i);
	}
}

template<class T>
void Heap<T>::Print()
{
	for(int i = 0; i < MinHeap.size();i++)
	{
		cout<<MinHeap[i]<<" ";
	}
	cout<<endl;
}


转载于:https://www.cnblogs.com/melons/p/5791880.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值