Testing if a linked list is equal to each other

喜夏-厌秋 提交于 2019-12-11 08:36:15

问题


I have a set of numbers that are in a linked list. I want to compare them to see if they are the same numbers in a set. Here is my code right now:

bool set::equalset(set second)
{
     Data *travel1, *travel2;
     travel1 = top;
     travel2 = second.topval(); //gets the top value for the second set
     while (travel2->next != NULL && travel1->next != NULL)
     {
           if (!in(travel2->value))  //in checks if the value is in the set
               return false;
           if (!second.in(travel1->value)) //same idea here
               return false;

           travel2 = travel2->next;
           travel1 = travel1->next;

           return true;
     }
     return false;
}

So what my code does is grab the top values for both of the sets and sets those equal to travel1/2 respectively, then while travel doesn't point to a null value in both sets, it traverses the lists and checks if values from either of the sets are in each other. If a value is not found, it sets it to false. Otherwise, it will be set to true and they are found to be equal.

However, this code only half works - you can easily break it by entering 1, 2 for the first set and 1, 2, 3 for the second set and they will be returned as equal. I would think that the third value (3) would make it return false. What is the missing link here?


回答1:


Your code has several problems. First, you're not checking the last node. A loop condition like this:

while (travel2->next != NULL && travel1->next != NULL)

will break as soon as one of the enumerators reaches the last node, but never checks it. Further, it will also mean two sets of a single-node-each will always compare true.

Next, You have a hard return after only the first iteration, so there is no conceivable way this ever returned false on two sets that started with the same node value.

travel2 = travel2->next;
travel1 = travel1->next;

return true; // this doesn't belong here.

Next, you pass your parameter by-value, which means the copy constructor is being invoked. I don't know whether you implemented it or not (and if you didn't, you have an entire different problem), but there is no reason to duplicate the list just to see if it is equal to *this*. The function should take a const-reference as the parameter.

bool set::equalset(const set& second)

Finally, your exit condition is correct, but you cannot assume the lists were both exhausted. you have to verify it. You can do this by returning false if either traveler is non-null (and one of them will be if the lists are uneven.

Putting it all together:

bool set::equalset(const set& second)
{
     const Data *travel1 = top;
     const Data *travel2 = second.top;
     while (travel1 && travel2)
     {
           if (!in(travel2->value))  //in checks if the value is in the set
               return false;
           if (!second.in(travel1->value)) //same idea here
               return false;

           travel2 = travel2->next;
           travel1 = travel1->next;
     }
     return !(travel1 || travel2);
}

Optimized for Sorted Lists

If you keep the lists sorted during input and removal methods, you can significantly make this easier, seen below:

bool set::equalset(const set& second)
{
     const Data *travel1 = top;
     const Data *travel2 = second.top;
     while (travel1 && travel2 && travel1->value == travel2->value)
     {
           travel1 = travel1->next;
           travel2 = travel2->next;
     }
     return !(travel1 || travel2);
}



回答2:


In the situation you describe, the first set's iterator will be NULL before the third element of the second set is searched for, breaking your while loop. You may as well loop through each set independently. You could also check if both sets have the same number of elements before comparing the elements of each.




回答3:


You need to adjust your return conditions because as of now, you return true if the first value in both this and second are present in each list.

Do something like this instead:

bool set::equalset(set second)
{
     Data *travel1, *travel2;
     travel1 = top;
     travel2 = second.topval(); //gets the top value for the second set

     while (travel2->next != NULL && travel1->next != NULL)
     {
           if (!in(travel2->value))  //in checks if the value is in the set
               return false;
           if (!second.in(travel1->value)) //same idea here
               return false;

           travel2 = travel2->next;
           travel1 = travel1->next;
     }
     return true;
}



回答4:


with your code if two sets have different number of members. your loop will exit as travel1 or travel2 which has less no. of elements will point to NULL, when other is still not NULL. In your case travel1 will point to NULL and there will still elements to parse in travel2

Check by below code

bool set::equalset(set second)
{
     Data *travel1, *travel2;
     travel1 = top;
     travel2 = second.topval(); //gets the top value for the second set
     while (travel2->next != NULL && travel1->next != NULL)
     {
           if (!in(travel2->value))  //in checks if the value is in the set
               return false;
           if (!second.in(travel1->value)) //same idea here
               return false;

           travel2 = travel2->next;
           travel1 = travel1->next;


     }
     if (travel2->next == NULL && travel1->next == NULL)
     {
      return true;
     }
     return false;
}

In this code for two set with elements 1 2 2 and 1 2 it will return false



来源:https://stackoverflow.com/questions/20062652/testing-if-a-linked-list-is-equal-to-each-other

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!