C ++:STL链表 - + =重复节点

时间:2011-08-23 05:24:44

标签: c++ list stl linked-list

我正在使用一个使用STL链表的Polynomial类。其中一个功能要求我将两个多项式一起添加。由于某种原因,+ =运算符似乎是复制节点,而不是仅仅修改内容。

这是类声明:

class Polynomial
{
    public:

        Polynomial(pair<double,int>); //Specified constructor
        void add(const Polynomial&);
        void print();
    private:

        Polynomial(); //Default constructor
        list<pair<double,int> > terms;
};

这是添加成员函数:

void Polynomial::add(const Polynomial& rhs)
    {
    list<pair<double,int> >::const_iterator r;
    list<pair<double,int> >::iterator l;

    for(r=rhs.terms.begin(); r!=rhs.terms.end(); r++)
    {
        bool match=0;
        //Check to see if we have an existing nth order node
        for(l=terms.begin(); l!=terms.end(); l++)
        {
            //If we do, just add the coefficients together
            if(l->second == r->second)
            {
                l->first += r->first;
                match = 1;


            }       
        }

        //If there was no matching existing node, we need to find out
        //where to insert it into the list.
        if(!match)
        {
            l=terms.begin();
            bool inserted=0; //Sentinel for the loop

            while(l!=terms.end() && !inserted)
            {               
                //If there's only one term in the list
                //Just compare and stick it in front or behind the existing node
                if(terms.size()==1)
                {
                    int this_exp = l->second;
                    int exp_to_ins = r->second;
                    if(exp_to_ins > this_exp) terms.push_back((*r));
                    if(exp_to_ins < this_exp) terms.push_front((*r));
                    inserted = 1;

                }

                //If there's more than one node, we need to traverse the list
                if(terms.size()>1)
                {
                    if(l!=terms.begin())
                    {
                        int this_exp = l->second;
                        l++;
                        int next_exp = l->second;
                        int exp_to_ins = r->second;

                        //If the new node value is between the current and next node
                        //Insert between them.
                        if((this_exp < exp_to_ins) && (exp_to_ins < next_exp))
                        {
                            terms.insert(l,(*r));                    
                            inserted = 1;
                        }

                     } 
                     else if(l==terms.begin())
                     {
                        int this_exp = l->second;
                        int exp_to_ins = r->second;


                        //This will be the smallest order node
                        //Put it in the top spot
                        if(this_exp > exp_to_ins) 
                        {
                            terms.push_front((*r));
                            inserted = 1;
                        }

                        l++;                    
                     }                  

                }

            }

            //If we've traversed the list and can't find the right place
            //this must be the greatest order node in the list
            //so just tack it on the end.
            if(!inserted) terms.push_back((*r));

        }

    }


}

以正确的顺序对节点进行排序可以正常工作,但是我们有一个现有的n阶节点,而不是仅仅将系数加在一起,它保留了原始节点,但似乎是将第二个节点与系数相加,并且我不明白为什么。

如果我运行打印功能,那应该是F(x)= -2x ^ 7 + 3x ^ 6 - 11x ^ 5 - 2x ^ 4,相反我得到F(x)= -2x ^ 7 + 3x ^ 6 - 11x ^ 5 - 10x ^ 5。如果我调用列表中的size()函数,我得到4.但是如果我运行以下代码来打印列表中节点的信息:

stringstream test;   
for(i=terms.end(); i!=terms.begin(); i--)
{

    test << "Coefficient: " << i->first << " ";
    test << "Exp: " << i->second << endl;

}
cout << "Size: " << terms.size() << endl;
cout << test.str(); 

以下是输出:

系数:-10 Exp:5 系数:-2 Exp:7 系数:3 Exp:6 系数:-11 Exp:5

非常感谢任何帮助。

编辑:这是测试程序。

Polynomial p(pair<double, int>(-10, 5));
p.add(Polynomial(pair<double,int> (-2,4)));
p.add(Polynomial(pair<double,int> (3,6)));
p.add(Polynomial(pair<double,int> (-2,7)));
p.add(Polynomial(pair<double, int> (-1,5)));

3 个答案:

答案 0 :(得分:2)

你的add()函数似乎是正确的,除了print:

for(i=terms.end(); i!=terms.begin(); i--)
{    
    test << "Coefficient: " << i->first << " ";
    test << "Exp: " << i->second << endl;
}

这是完全错误的,并调用未定义的行为。 i最初是terms.end(),您是否取消引用它? items.end()返回 past-the-end 迭代器。即使我假设它正确一段时间,条件i!=terms.begin()意味着第一个元素永远不会打印!

所以修复就是这样:

for(list<pair<double,int> >::iterator i=terms.begin(); i!=terms.end(); i++)
{

    test << "Coefficient: " << i->first << " ";
    test << "Exp: " << i->second << endl;
}

它打印预期输出:

Size: 4
Coefficient: -2 Exp: 4
Coefficient: -11 Exp: 5
Coefficient: 3 Exp: 6
Coefficient: -2 Exp: 7

不正确吗?

您也可以在此处查看输出:http://www.ideone.com/p8mwJ


顺便说一句,代替add,您可以改为operator+=,而不是:{/ p>

const Polynomial& operator+=(const Polynomial& rhs)
{
    //same code as before
    return *this;
}

如果您这样写,那么您可以添加多项式:

Polynomial p(pair<double, int>(-10, 5));
p += Polynomial(pair<double,int> (-2,4));
p += Polynomial(pair<double,int> (3,6));
p += Polynomial(pair<double,int> (-2,7));
p += Polynomial(pair<double, int> (-1,5));

演示:http://www.ideone.com/aA1zF


我刚刚阅读了您的评论,并且知道您想要以相反的顺序打印它,在这种情况下,您可以使用rbegin()rend()代替begin()和{ {1}} as:

end()

我还建议你将for(list<pair<double,int> >::const_reverse_iterator i=terms.rbegin(); i!=terms.rend(); i++) { test << "Coefficient: " << i->first << " "; test << "Exp: " << i->second << endl; } 作为const函数:

print

更好的是重载void print() const //^^^^ this makes the function const!

无论如何逆序打印演示:http://www.ideone.com/Vk6XB

答案 1 :(得分:0)

您的测试循环(字符串流中的一个打印)不正确:取消引用end()迭代器是未定义的行为。可能你的“std :: list”是以循环方式实现的(即使用begin == end + 1),因此解除引用“end”会让你在测试循环中开始。

使用反向迭代器以相反的顺序打印列表:

for (i = list.rbegin (); i != list.rend (); ++i)
{
   test << "Coefficient: " << i->first ; // etc.
} 

答案 2 :(得分:0)

除了@Nawaz指出的问题外,Polynomial::add函数也存在问题。

如果执行了if(terms.size()==1)块,则会在列表中插入新项目。但是这会将列表的大小增加一个,因此if(terms.size()>1)块也将被执行。这可以再次插入相同的节点。

在while循环中进一步增加l,继续使用下一个节点,而不检查它是否有效(即不与terms.end()比较)。

可能会有更多这样的错误,但这些错误是在粗略一瞥之后出现的。