簡體   English   中英

合並兩個排序列表,為什么只在第一個列表上工作C ++

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

我編寫了有關合並兩個排序列表的代碼。 但是,僅head1運行而不是head2。 例如,head1:0 2 5 7 head2:0 5 8 9.輸出將是0 2 57。有人可以告訴我為什么嗎?

 #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();

}

這是我的輸出: 在此處輸入圖片說明

有用的讀物​​,使您了解一些術語: 什么是右值,左值,x值,glvalue和prvalue? 如果您已經知道這些術語的含義,請跳過鏈接。 如果您在繼續之前不閱讀它,那么您將獲得的不僅僅是答案的“如何解決錯誤”部分。

當從函數中按值返回值時 ,可以保證得到的是臨時副本1 所以在這里

node* getlink() { return link; }

您返回一個指向node的指針,但是指針本身是指針的副本。 它不是link ,它是link的臨時副本,僅存在足夠長的時間才能將其分配給其他對象。 使用上面鏈接的術語,這是一個右值。 所以在

result ->getlink() = head1;

head1分配給link的臨時副本,該副本僅head1分配所需的時間內存在。

將數據分配給僅存在幾納秒的副本並不會帶來什么好處,因此,定義C ++工作方式的聰明才智決定,這樣做確實是錯誤的,以致無法理解該程序將無法工作。 結果是您收到的錯誤消息。 您不能分配給右值,但是可以分配給左值。

那么如何將右值變成左值呢?

最簡單的方法是不返回臨時副本。 最簡單的方法是返回對指針的引用

node* & getlink() { return link; }

現在,您無需返回link的副本,而是返回...好吧,這取決於編譯器。 您可能會獲得link 您可能會得到指向link的指針。 如果編譯器認為您無法注意到( 按規則 ),則可能會得到zelda 整個函數可能會被編譯器剝離,並替換為類似link = head1簡單殘酷的東西。

只有當您深入了解編譯器設計或性能調整時,真正發生的事情才有意義。 但是,編譯器認為適合這樣做,

result ->getlink() = head1;

現在可以通過返回函數調用來分配head1進行link

這就是讓您在vec[99] = 11;std::vector設置值的魔力vec[99] = 11; mat(3,2) = 7;的自定義matrixmat(3,2) = 7;

上面僅說明了錯誤消息及其解決方法。 它不對程序邏輯是否正確提出任何要求。

1與引用的工作方式一樣,編譯器在此處的操作還有很多余地,並且如果要復制的對象很大或很麻煩,則編譯器將執行一些偷偷摸摸的藍精靈操作,以將該副本轉換為計算量較小的對象復制。 如果您感興趣,請查閱Copy Elision和RVO的許多版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM