简体   繁体   中英

Merging two sorted lists why just work on the first list C++

I wrote the code about merging two sorted lists. However,just the head1 running not the head2. For example, head1: 0 2 5 7 head2: 0 5 8 9. The output will be 0 2 5 7. Could anyone tell me why?

 #include <iostream>
    using namespace std;
    // class node
    class node {
    private:
        double num;
        node *link;
    public:
        node() { }
        node(double m, node *n) { num = m; link = n; }
        node* getlink() { return link; }
        double getdata() { return num; }
        void setdata(double m) { num = m; }
        void setlink(node* n) { link = n; }
    };

typedef node* nodeptr;

void insertnode(nodeptr& head, double m);
void printlist(nodeptr head);
nodeptr mergelists(nodeptr& head1, nodeptr& head2);
void reverselist(nodeptr& head);
nodeptr search(nodeptr head, double searchterm);
void insert(nodeptr afterme, double newdata);
int main()
{
    double input;
    nodeptr head1 = NULL;       // Pointer to the head of List #1
    nodeptr head2 = NULL;       // Pointer to the head of List #2
    nodeptr temp;

    // Part 1 - Create two sorted lists
    cout << "-------------------------------------" << endl;
    cout << "CREATE LIST #1: " << endl;
    cout << "-------------------------------------" << endl;
    do {
        cout << "Enter value (0 to quit): ";
        cin >> input;
        // Insert the "input" value into the list
        insertnode(head1, input);
    } while (input != 0);

    cout << "-------------------------------------" << endl;
    cout << "CREATE LIST #2: " << endl;
    cout << "-------------------------------------" << endl;
    do {
        cout << "Enter value (0 to quit): ";
        cin >> input;
        // Insert the "input" value into the list       
        insertnode(head2, input);
    } while (input != 0);

    // Part 1 - Print the lists to make sure that they are correct.
    printlist(head1);
    printlist(head2);
    // Part 2 - Merge the two lists and display the new merged list
    cout << "Merge lists: " << endl;
    temp = mergelists(head1, head2);
    printlist(temp);
    // Part 3 - Reverse the merged list and then display it

    return 0;
}

nodeptr search(nodeptr head, double searchterm) 
{
    nodeptr p = head;
    nodeptr q = head->getlink();
    if (p == NULL)
        return NULL;
    else
    {           

        while (p != NULL)
        {
            q = p->getlink();
            while (q != NULL && q->getdata() < searchterm)
            {
                p = p->getlink();
                q = q->getlink();
            }
            return p;
        }
    }
}

void insertnode(nodeptr& head, double m)
{
    // CASE 1 - List is empty
    if (head == NULL)
    {
        head = new node(m, NULL);
    }

    // CASE 2 - List is not empty and new value is < 1st value
    else if (m < head->getdata())
    {
        head = new node(m, head);
    }

    // CASE 3 - List is not empty and new value goes inside list
    else
    {
        // search for correct location - notes on Search
        nodeptr afterme = search(head,m);
        // insert at this location -- see notes on insert inside list
        nodeptr temp;
        temp = new node(m, afterme->getlink());
        afterme->setlink(temp);
    }
}

void printlist(nodeptr head)
{
    nodeptr p;
    p = head;
    while (p != NULL)
    {
        cout << p->getdata() << endl;
        p = p->getlink();
    }
}
// mergelist function -> wrong result
nodeptr mergelists(nodeptr& head1, nodeptr& head2)
{
    if (head1 == NULL)
        return head2;
    if (head2 == NULL)
        return head1;
    nodeptr result = new node(0, NULL);
    nodeptr head = result;
    while (head1 != NULL&&head2 != NULL){
        if (head1->getdata() <head2->getdata()){
            result ->getlink() = head1;
            head1 = head1 -> getlink();
        }
        else{
            result->getlink() = head2;
            head2 = head2->getlink();
        }
        result = result ->getlink();
    }

    if (head1 == NULL){
        result ->getlink() = head2;
    }
    else{
        result ->getlink() = head1;
    }

    return head->getlink();

}

Here is my output: 在此处输入图片说明

Helpful reading so you know a bit of terminology: What are rvalues, lvalues, xvalues, glvalues, and prvalues? If you already know what those terms mean, skip the link. If you don't read it before continuing and you will get a lot more than just the "How to fix the error" portion of this answer.

When you return a value from a function by value , all you are guaranteeed is you get a temporary copy 1 . So here

node* getlink() { return link; }

you return a pointer to a node , but the pointer itself is a copy of a pointer. It's not link , it is a temporary copy of link that only exists long enough to assign it to something else. Using the terminology linked above, this is an rvalue. So in

result ->getlink() = head1;

head1 would be assigned to a temporary copy of link that only exists for as long as it takes to do the assignment.

You don't get much from assigning data to a copy that only exists for a few nanoseconds, so the big brains who define how C++ works decided that doing it should be an error to drive home the point that the program will not work. The result is the error message you got. You can't assign to an rvalue, but you can assign to an lvalue.

So how do we turn an rvalue into an lvalue?

The easiest way is to not return a temporary copy. The easiest way to do that is to return a reference to the pointer

node* & getlink() { return link; }

Now instead of returning a copy of link , you return... Well that depends on the compiler. You might get link . You might get a pointer to link . If the compiler figures you won't be able to notice ( the As-If Rule ) you might get zelda instead. That whole function might be stripped out by the compiler and replaced with something brutally simple like link = head1 .

What really happens only matters when you get down into the nitty-gritty of compiler design or performance tuning. However the compiler sees fit to do it,

result ->getlink() = head1;

can now assign head1 to link through the return of the function call.

This is the magic that allows you to set a value in a std::vector with vec[99] = 11; or a custom matrix class with mat(3,2) = 7;

The above only explains the error message and how to fix it. It makes no claims on whether or not the logic of the program is correct.

1 As with how a reference works, the compiler has a lot of leeway about what it does here, and the compiler is going to do some really sneaky smurf to turn that copy into something less computationally intensive if the object being copied is large or troublesome to copy. Look up Copy Elision and the many flavours of RVO if you are interested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM