一,什么是堆
堆:(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;
}
运行结果:
四,取出元素(出队):
对于最大堆的出队,就是优先级高的先出队,也就是根结点;如果取出根结点,要将堆中的最后一个元素放在根结点的位置,具体做法如下:
取出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;
}
运行结果:
下一篇:堆排序优化
总结:认真领悟: