最近在学慕课上浙江大学数据结构的课程,记录一下过程。以免后面忘记了。
下面是第五讲-树(下)关于堆的内容
1. 概念
在讲堆之前先讲了优先队列(priority queue)的含义,一般的队列是按照先近先出的原则,也就是谁先请求,就先响应谁。但是在很多情况下,先请求的任务不一定有后请求的任务重要,不同任务的重要性,权重不同。 因此在队列中,就应该优先取出权重大的元素,而不一定是最先进入队列的元素。这种优先队列也需要一种存储结构,数组或者链表。选择一种特殊的完全二叉树来表示这种优先队列,这种二叉树有两种特性:
1.使用数组来存储这种完全二叉树,所以在数组中父节点的索引值是其左右孩子索引值的一半,parent=child/2;
2. 这种完全二叉树从根节点一层层往下具有一定的顺序,升序或者降序,如果根节点大于其左右孩子为,为最大堆,反之为最小堆
2. 堆的数组表示及插入删除操作
可以将堆作为一个类封装起来,下面考虑该类的数据成员和函数成员
数据成员:
1).首先要有一个指针*data(指向某一数组的首地址),指向一个数组,
2)然后需要一个整形变量capacity,存储数组的容量;
3)最后需要一个变量size,数组表示实际的大小
函数成员:
函数成员主要是对这个堆的操作,包括插入,删除,打印节点到跟的路径等等;
在A*算法中,如果openlist使用最小堆存储其中的数据(并按F值大小为排序基准),如果当前节点周围8个待扩展节点,有的已经处于openlist中了,那么需要判断这些节点通过当前节点到达起点的G1是否比之前的G0要小,如果G1<G0,则需要将这个节点的父节点调整为当前节点,此时的F1=G1+H肯定就比原来的F0要小了,所以需要调整相应二叉树中各个节点的位置,此时只需要将待调整的节点的F值向二叉树的上行方向比较,若比其二叉树中的“父”节点的F值小则交换位置,否则不用调整位置。

3. 代码实现
#include "stdafx.h"
#include<iostream>
using namespace std;
MinHeap::MinHeap(int cap)
{
capacity = cap;
size = 0;
date = new int[cap + 1];
date[0] = -20000;
}
int MinHeap::Insert(int x)
{
if (size == capacity)
{
cout << "堆已满" << endl;
return 0;
}
int i = ++size;
for (;date[i/2]>x;i/=2)
{
date[i] = date[i / 2];
}
date[i] = x;
return 1;
}
int MinHeap::Delete()
{
if(size==0)
{
cout << "堆为空,无法删除" << endl;
return 0;
}
int minDate = date[1];
int temp = date[size];
size--;
int parent = 1;
int child;
for (;parent*2<=size;parent=child)
{
child = 2 * parent;
if ((child!=size) && (date[child]>date[child+1]))
{
child++;
}
if (date[child] >= temp)
break;
else
date[parent] = date[child];
}
date[parent] = temp;
return minDate;
}
MinHeap::~MinHeap()
{
delete [] date;
}
void MinHeap::printPath(int i)
{
if (i>size || i<1)
{
cout << " 打印的i非法" << endl;
}
for (int j=i;j>1;j=j/2)
{
cout << date[j] << " ";
}
cout << date[1] << endl;
}
void MinHeap::Adjust(int index)
{
int parent = 0.5*index;
while(date[index]<date[parent])
{
int temp = date[parent];
date[parent] = date[index];
date[index] = temp;
index = 0.5*index;
parent = 0.5*index;
}
}