所以我有这个小程序,它创建一个最小堆并根据用户输入插入值。如果用户将值更改为10到20,则程序应将所有出现的值更改为10到20,然后进行堆积。当用户给出打印命令时,程序应该在后序中遍历树并打印所有值。所以我编写了程序但是在打印时它给了我不正确的输出。我在这做错了什么:
int pArray[500];
int i = 0;
//Definition of Node for tree
struct TNode {
int data;
TNode* left;
TNode* right;
};
void Heapify(TNode* root, TNode* child);
// Function to create a new Node in heap
TNode* GetNewNode(int data) {
TNode* newNode = new TNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
// To insert data in the tree, returns address of root node
TNode* Insert(TNode* root,int data) {
if(root == NULL) { // empty tree
root = GetNewNode(data);
}
// if the left child is empty fill that in
else if(root->left == NULL) {
root->left = Insert(root->left,data);
}
// else, insert in right subtree.
else if(root->right == NULL){
root->right = Insert(root->right,data);
}
else {
root->left = Insert(root->left,data);
}
Heapify(root, root->left);
Heapify(root, root->right);
return root;
}
void Heapify(TNode* root, TNode* child){
if(root != NULL && child != NULL){
if(root->data > child->data){
int temp = child->data;
child->data = root->data;
root->data = temp;
}
}
}
void Change(TNode* root,int from, int to) {
if (root == NULL)
return;
else if (root->data == from)
root->data = to;
Change(root->left, from, to);
Change(root->right, from, to);
}
void postOrder(TNode* n){
if ( n ) {
postOrder(n->left);
postOrder(n->right);
pArray[i] = n->data;
i++;
}
}
答案 0 :(得分:2)
我在这里做错了什么?
我打算假设您在打印之前已经验证了堆。你的树实现有点令人困惑,但看起来它应该工作。但是,我建议你做的第一件事是在调用Change
方法之前打印树,只是为了确保你有一个有效的堆。
假设您有一个有效的堆,您的Change
方法存在问题:它永远不会调用Heapify
。您最终会更改堆中的值而不是重新排列。所以当你输出它时,它当然会出现故障。
当您更改项目的值时,您必须在更改任何其他值之前将该节点(或节点的值)移动到树中的正确最终位置。您可以使用当前模型(通过重复调用Heapify
直到节点处于正确位置)。只要你增加价值。如果您正在减小该值(即将值更改为20到10),那么您就会遇到问题,因为您的代码无法将项目向上移动。
正如@noobProgrammer在他的评论中所指出的,二进制堆通常被实现为数组而不是树。以这种方式实现起来要容易得多,使用的内存更少,效率也更高。如果您对如何完成感兴趣,您应该阅读我关于堆和优先级队列的多部分博客系列。第一个条目Priority queues描述了问题。从那里,您可以按照链接了解二进制堆及其实现方式。代码示例在C#中,但如果您阅读前两篇介绍性文章并理解这些概念,您将能够毫无困难地转换为C ++。