堆排序的c++实现

下面是几个函数原型:


求左孩子、右孩子、及父节点的下标的三个函数分别如下(本实例是直接是0为初始下标的计算,与1为初始下标的计算有点不同):



维护最大堆的性质(用递归的方法):这个可以理解为,保证一个节点满足最大堆的性质



建堆过程:在没有子节点的节点开始,通过调用维护堆性质,依次到根节点。



最后是排序过程:通过最大堆的最后一个与根节点(最大)交换,此时换上去的根节点很大可能不满足最大堆性质,所以要维护此时的跟节点,让其满足。然后重复这一过程,每重复这一过程,最大堆的规模减一。


最后是测试函数(在main函数中测试啦):



下面是调试结果:


 总结:我在调试这个程序的时候,建堆的时候没有把根节点的位置遍历,也就是说我之前写的代码是 


这个结果会导致最上面的那个根节点位置还需要维护最大堆的性质;

我调试了很久一直没有发现这个错误。所以我要特别感谢一位毕业的师兄帮我发现了这个问题。---肖某;
参考书目:算法导论第三版


下面附上可复制形式的代码:

#include "iostream"
using namespace std;
int parent(int i);//父节点
int left(int i);//左孩子
int right(int i);//右孩子
void max_heapify(int* arr, int n_long, int i);//维护最大堆性质
void build_max_heap(int* arr, int n_long);//建堆
void heapsort(int* arr, int n_long);//堆排序

int main()//测试
{
	int n;
	cout << "please enter the size of arr: ";
	cin >> n;
	int* arr = new int[n];
	cout << "please enter arry" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];
	}

	heapsort(arr, n - 1);
	for (int i = 0; i<n; i++)
	{
		cout << arr[i] << endl;
	}

	cin.get();

	cin.get();
	return 0;


}


int parent(int i)
{
	if (i / 2 == 0)
		return i / 2 - 1;
	return i / 2;
}

int left(int i)
{
	return 2 * i + 1;
}

int right(int i)
{
	return 2 * i + 2;
}

void max_heapify(int* arr, int n_long, int i)
{
	int l = left(i);
	int r = right(i);
	int largest;

	if (l <= n_long && arr[l]>arr[i])
		largest = l;

	else
		largest = i;
	if (r <= n_long and arr[r]>arr[largest])
		largest = r;
	if (largest != i)
	{
		int b = arr[largest];
		arr[largest] = arr[i];
		arr[i] = b;
		max_heapify(arr, n_long, largest);
	}
}


void build_max_heap(int* arr, int n_long)
{
	int i;
	if (n_long / 2 == 0)
	{
		i = n_long / 2 - 1;
	}
	else
		i = n_long -1/ 2;

	for (; i>0; i--)
		max_heapify(arr, n_long, i);
}

void heapsort(int* arr, int n_long)
{
	build_max_heap(arr, n_long);
	for (int i = n_long; i>0; i--)
	{
		int b = arr[0];
		arr[0] = arr[n_long];
		arr[n_long] = b;
		n_long--;
		max_heapify(arr, n_long, 0);
	}
}









猜你喜欢

转载自blog.csdn.net/lily559/article/details/80568481
今日推荐