gpt4 book ai didi

c++ - 我是否正确实现了 "Heapify"算法?

转载 作者:IT老高 更新时间:2023-10-28 22:03:28 28 4
gpt4 key购买 nike

我正在为计算机科学类(class)创建一个堆实现,我想知道下面的递归函数是否会从一个还不是堆的数组对象中创建一个堆。代码如下:

void Heap::Heapify(int i)
{
int temp, l, r, heapify;
l = LeftChild(i);// get the left child
r = RightChild(i);// get the right child

//if one of the children is bigger than the index
if((Data[i] < Data[l]) || (Data[i]< Data[r]))
{
//if left is the bigger child
if(Data[l] > Data[r])
{
//swap parent with left child
temp = Data[i];
Data[i] = Data[l];
Data[l] = temp;
heapify = l; // index that was swapped
}
//if right is the bigger child
else
{
//swap parent with right child
temp = Data[i];
Data[i] = Data[r];
Data[r] = temp;
heapify = r; // index that was swapped
}
// do a recursive call with the index
//that was swapped
Heapify(heapify);
}
}

这个想法是,您可以查看给定索引处的数据是否大于其所有子项。如果是,则函数结束没有问题。否则,它检查哪个是最大的(左或右 child ),然后将其与索引交换。然后在发生交换的索引处调用 heapify。

应 ildjarn 的要求,我将包含完整的类定义和实现文件,以帮助回答我的问题:
这是头文件:

#ifndef HEAP_H
#define HEAP_H
//Programmer: Christopher De Bow
//Date: november 15, 2011

class Heap
{
private:
int Data [100];
int Parent(int);
int RightChild(int);
int LeftChild(int);
void Heapify(int);
void BuildHeap();

public:
Heap();
void insert();
void HeapSort();
void ExtractMaximum();
int Maximum();
void PrintHeap();
int heapsize;
void SetData(int[]);
};

#endif

以及实现文件:

#include <iostream>
#include "Heap.h"
using namespace std;
//Programmer: Christopher De Bow
//Date: november 15, 2011

Heap::Heap()
{
int init [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
heapsize = 10;
SetData(init);
}

int Heap::Parent(int index)
{
int Rval;
if(index%2 == 0)// if the index is even
{
Rval = ((index-1)/2);
}
else// if the index is odd
{
Rval = (index/2);
}
return Rval;
}

int Heap::RightChild(int arrplace)
{
int ret;
ret = ((2*arrplace)+2); //rightchild is index times 2 plus 2
return ret;
}

int Heap::LeftChild(int i)
{
int rval;
rval = ((2*i)+1); //leftchild is index times 2 plus 1
return rval;
}

void Heap::Heapify(int i)
{
int temp, l, r, heapify;

l = LeftChild(i); // get the left child
r = RightChild(i); // get the right child

if((l <= heapSize) && (data[l] > data[i]))
{
heapify = l;
{
else
{
heapfiy = i;
}
if((r <= heapSize) && (data[r] > data[heapify]))
{
heapify = r;
}
if(heapify != i) // one of the two child nodes has proved
{ // larger than Data[i], so interchange values
//swap parent with left child
temp = Data[i];
Data[i] = Data[heapify];
Data[heapify] = temp;
Heapify(heapify);
}
}

void Heap::BuildHeap()
{
// we do not have a heap
// we will make a heap
// by calling heapify starting at the lowest
// internal node in the heap
for(int i = heapsize; i >= 1; i--)
{
Heapify(i-1);
}
}

void Heap::insert()
{
int insert;
heapsize = (heapsize + 1);
//getting data from the user
cout<<"what data would you like to insert?"<<endl;
cin>>insert;
Data[heapsize] = insert;
BuildHeap(); //call BuildHeap on array
cout<<"done"<<endl;
}

void Heap::PrintHeap()
{
BuildHeap();
for(int count = 0; count < (heapsize-1); count++)
{
cout<<Data[count];// print out every element in heap
}
cout<<endl<<endl;
}

void Heap::HeapSort()
{
BuildHeap();
int temp;
// do this for every elem in heap:
for(int i = 0; i < heapsize; i++)
{
temp = Data[heapsize-1];
Data[heapsize-1] = Data[0];
Data[0] = temp;
heapsize--;
BuildHeap();
}
PrintHeap();
}

void Heap::ExtractMaximum()
{
BuildHeap();
//assign last thing in heap to first thing in heap
Data[0] = Data[heapsize];
heapsize --; // decrease heapsize by one
Heapify(0); // heapify from the top
}

int Heap::Maximum()
{
int Rval;
BuildHeap();// make sure we have a heap
Rval = Data[0];
return Rval; // return top thing
}

//initialize the elements in the "Data" array
void Heap::SetData(int x[])
{
for(int i = 0; i <= (heapsize); i++)
{
Data[i] = x[i];
}
}

最佳答案

您的算法有效。问题在于算法到代码的转换。假设您将 Data 声明为:

int Data[7];

然后用初始值 {0, 1, 2, 3, 4, 5, 6} 填充它。假设 LeftChild(i)RightChild(i) 的定义类似于:

#define LeftChild(i) ((i << 1) + 1)
#define RightChild(i) ((i << 1) + 2)

然后你的函数BuildHeap(),应该是这样的:

void Heap::BuildHeap()
{
for(int i = (7 >> 1); i >= 1; i--) // in general, replace 7 with
// (sizeof(Data)/sizeof(int)), presuming
// you have an array of int's. if not,
// replace int with the relevant data type
Heapify(i-1);
}

将在最右下角的子树根上开始 Heapify 进程。在这种情况下,这是数组索引 2,左 child 为 5,右 child 为 6。Heapify 将正确交换 2 和 6 并递归调用 Heapify(6).

在这里,整个事情都可能搁浅!目前你的树看起来像:

                         0
1 2
3 4 5 6
u n d e f i n e d s p a c e

所以调用 Heapify(6) 将尽职尽责地比较 Data[6]Data[13] 的值Data[14](与 Java 不同,C++ 的危险及其缺乏数组边界强制执行)。显然,后两个值可以是 RAM 中留下的任何垃圾。这里的一个解决方案,丑陋但有效的补丁,是在 Data 的声明中添加 8 个元素,并将它们全部初始化为低于数组中任何元素的某个值。更好的解决方案是向您的类添加一个 heapSize 变量并将其设置为等于数组的长度:

heapSize = (sizeof(Data)/sizeof(int));

然后整合逻辑只比较子节点,如果它们是树的有效叶子。一个有效的实现是:

void Heap::Heapify(int i)
{
int temp, l, r, heapify;

l = LeftChild(i); // get the left child
r = RightChild(i); // get the right child

if((l <= heapSize) && (Data[l] > Data[i]))
heapify = l;
else heapfiy = i;
if((r <= heapSize) && (Data[r] > Data[heapify]))
heapify = r;
if(heapify != i) // one of the two child nodes has proved
// larger than Data[i], so interchange values
{
//swap parent with left child
temp = Data[i];
Data[i] = Data[heapify];
Data[heapify] = temp;

Heapify(heapify);
}
}

总而言之,解决方案就像添加逻辑一样简单,以确保子节点是树的有效叶子,并且您的 main 函数将具有以下内容:

Heap heap;

// initialize Data here

heap.BuildHeap();

希望对您有所帮助。

关于c++ - 我是否正确实现了 "Heapify"算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8130177/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com