数据结构-堆

最近在学慕课上浙江大学数据结构的课程,记录一下过程。以免后面忘记了。

下面是第五讲-树(下)关于堆的内容

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;
	 }

 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值