我对这个非常简单的代码块有疑问。请给我你的建议。 (我的这个问题已经解决,在解决这个问题时,有id stakx的人确实对我有帮助,唯一的问题是我正在使用stack< treeNode>,当我仔细看到堆栈的推送方法时,那里是一个复制过程,当我写head-> object = number,所以最后我做了一堆指针,就像这个堆栈< treeNode *>它真的解决了问题,我现在没问题,我非常感谢对stakx的人。)
在代码之前需要支持以下树
alt text http://img44.imageshack.us/img44/7016/avlimage06.jpg
你可以在图片中看到root是8,stack有两个节点,即6和4.我将这个堆栈和根节点传递给下面的代码
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
{
if(!s.isempty())
{
treeNode *stacknode;
stacknode=s.pop();
cout<<"\ninside the attachwithtree function, stack node is "<<stacknode->data;
stacknode->right=tree;//attaching the passed node to the right of popped node
root=stacknode;//setting the root to stack node which is the private data member of class
updatebalance(root);//this function is ok, it does not create problem
while(!s.isempty())
{
cout<<"\nstack is still not empty";
stacknode=s.pop();
cout<<"\nright side of "<<root->data<<" is "<<(root->right)->data;
//the below three lines causing the problem i don't know why,
root=stacknode;
treeNode* temp;
temp=root->right;
cout<<"\n\n\nthe right side of "<<temp->data<<" is now "<<(temp->right)->data;
updatebalance(root);
}
此函数的输出由下式给出
alt text http://img704.imageshack.us/img704/5976/avlimage07.jpg
这是我正在使用的堆栈的pop方法的代码
template <class t>
t * Stack<t>::pop()
{
if(topelement!=NULL)
{
t* num;
current=topelement;
num=&(current->object);
topelement=topelement->preptr;
current=topelement;
return(num);
}
else
{
head=NULL;
}
}
这是堆栈推送方法的代码
template <class t>
void Stack<t>::push(t &number)
{
Node<t>* newNode=new Node<t>;
if(head==NULL)
{
head=newNode;
topelement=newNode;
current=newNode;
head->object=number;
head->preptr=NULL;
}
else
{
topelement=newNode;
newNode->preptr=current;
current=topelement;
newNode->object=number;
}
}
答案 0 :(得分:4)
可能是堆栈上的节点4
在其右侧(节点为6
右侧)的节点7
与节点{{1}之间的节点6
不同(你右边的节点8
)你在做什么?您可以比较它们的地址,以确保您没有两个不同的节点6
副本。
让我们看一下你方法的签名:
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
s
被定义为对Stack<treeNode>
的引用。
是不是应该是Stack<treeNode*>
?
根据您的treeNode
课程,当您在此堆栈上推送X
时,您实际上最终会得到X
而非X
本身的副本。同样,当你从堆栈中弹出时,你可能实际上并没有得到你推送的项目,而是一个看起来相同的副本!?
这意味着,当您在堆栈上推送节点6
时,其右子节点是节点7
。但是你已经在堆栈上推送了一个新的,相同的节点。即使您从堆栈中弹出此元素并进行更改,您也只需更改副本并保留原始树节点。
因此,您将在节点6
的不同副本上操作。首先,从堆栈中弹出它的副本,并将树附加为其右子。选中此项将得到正确的结果。
然后,从堆栈中弹出节点4
的副本。正确的孩子是节点6
,正如预期的那样,但不是您刚修改的那个,而是原始的!因此,您会在节点7
的右侧获得6
。
好的,这是使用指针或引用时需要了解的内容。它基本上显示了通过值传递参数(将创建副本)或通过引用传递它(不会创建副本)之间的区别。
仔细研究,然后看看它如何适用于您的问题。
#include <iostream>
class someObject
{
private:
int _value;
public:
someObject(int value) : _value(value) { }
int getValue()
{
return _value;
}
};
void someFunction(someObject objCopy, someObject* objPtr)
{
std::cout << "objCopy.getValue() -> " << objCopy.getValue() << std::endl;
std::cout << "objPtr->getValue() -> " << objPtr->getValue() << std::endl;
if ( &objCopy != objPtr )
{
std::cout << "objCopy is not actually *objPtr but a copy of it." << std::endl;
}
else
{
std::cout << "objCopy and *objPtr are one and the same object." << std::endl;
}
}
int main()
{
someObject X(17);
someFunction(X, &X);
return 0;
}
提示:是的,在您的pop
方法中,您使用指针,但很可能使用指向最初在堆栈上推送的对象副本的指针。
答案 1 :(得分:1)
这是你自己的Stack类吗?快速浏览STL告诉我pop()的返回类型为void。
这可能是stakx在这里的东西。如果pop()函数返回top元素的副本而不是对它的引用,则您所做的更改将仅应用于副本。在修改后,您是否明确地将副本添加回树中?