5

我对这个非常简单的代码块有疑问。请给我你的建议。 (我的这个问题解决了,在解决这个问题时,id stakx 的人真的帮了我,唯一的问题是我在使用堆栈<treeNode>,当我仔细看到堆栈的推送方法时,有一个复制过程当我写 head->object=number 时,所以最后我做了一个指针堆栈,就像这个堆栈<treeNode*>,它确实解决了问题,我现在没有问题,我非常非常感谢 stakx 人。)

在代码之前,您需要提供以下树

替代文本 http://img44.imageshack.us/img44/7016/avlimage06.jpg
,如图所示,根为 8,堆栈有两个节点,即 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);
}

该函数的输出由下式给出
替代文字


这是我正在使用的堆栈的 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;
}
}


这是堆栈的push方法的代码

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

2 回答 2

4

原答案:

4堆栈上的节点在6其右侧(右侧有节点的那个)与您正在处理7的节点6(右侧有节点)是否有不同的节点?8您可以比较他们的地址以确保您周围没有两个不同的节点副本6

对上述论点的阐述:

让我们看看你的方法的签名:

void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)

s被定义为对 a 的引用Stack<treeNode>

难道它应该是一个Stack<treeNode*>

根据您的treeNode班级,当您推入X此堆栈时,您实际上可能会得到一个副本X而不是X它本身。同样,当您从堆栈中弹出时,您可能实际上并没有得到您推送的项目,而是一个外观相同的副本!?

这意味着,当您将 node 压入6堆栈时,它的右孩子是 node 7。但是您已经在堆栈上推送了一个新的、相同的节点。即使您从堆栈中弹出该元素并对其进行更改,您也只会更改一个副本并保持原来的树节点与以前一样。

因此,您将对 node 的不同副本进行操作6。首先,您从堆栈中弹出它的副本,并附加一棵树作为其右孩子。检查这将给出正确的结果。

4然后,从堆栈中弹出节点的副本。正确的孩子是 node 6,正如预期的那样,不是你刚刚修改的那个,而是原来的!因此,您7位于 node 的右侧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方法中,您使用指针,但很可能使用指向最初压入堆栈的对象副本的指针。

于 2010-01-16T09:32:23.210 回答
1

那是你自己的 Stack 类吗?快速浏览一下 STL 告诉我 pop() 的返回类型为 void。

可能是 stakx 在这里有所作为。如果您的 pop() 函数返回顶部元素的副本而不是对其的引用,则您所做的更改将仅适用于副本。您是否在修改后将副本显式添加回树中的任何位置?

于 2010-01-16T10:36:06.230 回答