堆排序

一,什么是堆

堆:(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象,

堆总是满足下列性质:
  • 1,堆中某个节点的值总是不大于或不小于其父节点的值;
  • 2,堆总是一棵完全二叉树。
  • 3,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

如下图为最大堆:


注意:最后一层没有饱和,但是节点必须从左边开始排起,这样才能满足最大堆。


二,堆的实现:

观察下图:


可以通过数组来实现堆,且将第一个结点从数组下标1开始;


对于结点i,

其父结点:i/2;

其左孩子:2*i;

其有孩子:2*i+1;

代码:

定义一个头文件:HeapSort.h:

class MaxHeap
{
private:
	int *data;//记录数据
	int count;//记录堆中的元素个数
public:
	MaxHeap(int capacity);//开辟空间
	int size();//元素个数
	bool isEmpty();//是否为空
	~MaxHeap();//释放空间

private:

};

MaxHeap::MaxHeap(int capacity)
{
	data = new int[capacity];
	count = 0;
}

MaxHeap::~MaxHeap()
{
}
int MaxHeap::size() {
	return count;
}

bool MaxHeap::isEmpty() {
	return count==0;
}

在main中:完成堆的创建

#include<iostream>
#include"HeapSort.h"
using namespace std;



int main() {

	MaxHeap maxheap =  MaxHeap(100);//创建堆

	return 0;
}


三,添加数据:

添加一个值(入堆):50,如图


显然不满足最大堆要求:50>35,所以要将50和35交换;


同样,43<50,不满足要求,继续交换;


最终完成了插入:

代码:

在MaxHeap中添加方法:insert(int),shiftUp(int );print();

void MaxHeap::insert(int item) {
	//判断容量是否已满
	if (count <= capacity) {
		//添加值
		data[count + 1] = item;
		count++;
		shiftUp(count);
	}
	
}

void MaxHeap::shiftUp(int k) {
	//判断k的合法性以及交换条件
	while (k > 1 && data[k] > data[k / 2]) {
		swap(data[k], data[k / 2]);
		k /= 2;
	}
}
void MaxHeap::print() {


	for (int i = 1; i <= count; i++)
	{
		cout << data[i]<<" ";
	}
	
}

main函数中:

#include<iostream>
#include"HeapSort.h"
using namespace std;



int main() {

	int arr[20] = { 0,60,43,52,40,35,44,35,20,34,25 };
	MaxHeap maxheap =  MaxHeap(100);//创建堆
	for (int i = 1; i <=10; i++)
	{
		maxheap.insert(arr[i]);
	}

	cout << "before insert:" ;
	maxheap.print();
	cout << endl;

	maxheap.insert(50);

	cout << "after  insert:";
	maxheap.print();
	cout << endl;


	return 0;
}

运行结果:


和预期一样,50放到了正确的位置上了。


四,取出元素(出队):

对于最大堆的出队,就是优先级高的先出队,也就是根结点;如果取出根结点,要将堆中的最后一个元素放在根结点的位置,具体做法如下:


取出60,则将25放在60原来的位置,count--,此时情况如图:


此时发现:并不满足最大堆的条件,需要将25放在合适的位置,找到它的两个孩子,取值最大的那个孩子与子交换,(为啥不取小的那个,取小的放在头结点,就有不满足最大堆了)。43<52,所以52与25,交换。


还是没有满足,再继续进行同样操作:


此时已经满足了.

代码:

添加delete(),shiftDown();两个方法。

int MaxHeap::extractMax() {
int item=data[1];
	if (count > 0) {
		data[1] = data[count];
		count--;
		shiftDown(1);
	}
return item;
}
void MaxHeap::shiftDown(int k) {

	while (2*k<=count) {
		int j = 2 * k;
		if (j + 1 <= count&&data[j + 1] > data[j])
			j += 1;
		if (data[k] > data[j])
			break;
		
			swap(data[k], data[j]);
		k = j;
	}
}


在main中:

#include<iostream>
#include"HeapSort.h"
using namespace std;



int main() {

	int arr[20] = { 0,60,43,52,40,35,44,35,20,34,25 };
	MaxHeap maxheap =  MaxHeap(100);//创建堆
	for (int i = 1; i <=10; i++)
	{
		maxheap.insert(arr[i]);
	}

	cout << "before extractMax:" ;
	maxheap.print();
	cout << endl;

	maxheap.extractMax();
	cout << "after  extractMax:";
	maxheap.print();
	cout << endl;

	return 0;
}

运行结果:


和预期一样,这样完成了从堆中取出一个元素的操作。

五,排序:

通过出队的方式,最大堆每次出队都是最大的一个元素先出,所以可以将出队的元素进行简单操作就可以完成排序:

int main() {

	int arr[20] = {60,43,52,40,35,44,35,20,34,25 };
	MaxHeap maxheap =  MaxHeap(100);//创建堆
	
	for (int i = 0; i <10; i++)
	{
		maxheap.insert(arr[i]);
	}

	cout << "before sort:" ;
	maxheap.print();

	int arr1[10];
	for (int i = 9; i >=0; i--)
	{
		arr1[i]=maxheap.extractMax();
	}
	cout << endl;
	cout << "after  sort:";
	for (int i = 0; i <10; i++)
	{
		cout << arr1[i] << " ";
	}

	return 0;
}

运行结果:


 下一篇:堆排序优化

总结:认真领悟:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值