C ++中链接列表中的虚拟节点

时间:2015-07-18 12:12:28

标签: c++ algorithm pointers linked-list

我正在尝试开发一种方法,我可以解决链接列表问题,而不必以任何特殊方式关心头节点,即在链接列表问题中,我们通常在开始下一个节点之前单独处理头指针

我找到了一种方法:使用虚拟节点,以便实际的链表从dummy.next开始。

我正在尝试使用这种方式解决problem

 struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };

 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {

        ListNode dummy = ListNode(0);
        ListNode * temp = dummy.next;
        int carry =0;

        while(l1!=NULL && l2!=NULL)
        {
            int x = (l1->val + l2->val + carry)%10;
            temp = new ListNode(x);
            carry = (l1->val + l2->val + carry)/10;
            temp = temp->next;
            l1 = l1->next;
            l2 = l2->next;
        }

        ListNode * p = (l1!=NULL)?l1:l2;

        while(p!=NULL)
        {
            int x = (p->val+carry)%10;
            temp = new ListNode(x);
            carry = (p->val+carry)/10;
            temp = temp->next;
            p = p->next;
        }

        if(carry==1) temp = new ListNode(1);

        return dummy.next;

    }

int main()
{
    ListNode * l1 = new ListNode(0), *l2 = new ListNode(0);
    ListNode * l3 = addTwoNumbers(l1,l2);

}

在这个问题中,我尝试不单独初始化头节点。显然,代码不能达到我想要的目的,但我尝试了这种方式,现在,我无法弄清楚如何继续这种方法。

即,使用虚拟节点,这样就不需要单独处理新创建的链表的头节点。

使用这种方法解决问题的方法是什么?

3 个答案:

答案 0 :(得分:2)

遵循这种方法

<html>
<head>
<title>Bing Search Tester (Basic)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>Bing Search Tester (Basic)</h1>
<form method="POST" action="bing_basic.php">
<label for="service_op">Service Operation</label><br/>
<input name="service_op" type="radio" value="Web" CHECKED /> Web
<input name="service_op" type="radio" value="Image" /> Image <br/>
<label for="query">Query</label><br/>
<input name="query" type="text" size="60" maxlength="60" value="" /><br /><br />
<input name="bt_search" type="submit" value="Search" />
</form> <h2>Results</h2>
{RESULTS} 
</body>
</html>

答案 1 :(得分:1)

无论是否有虚拟节点,构建新列表的关键部分都是将一个节点留在逻辑上的位置。我更喜欢在没有虚节点的情况下这样做,因此用于当前位置的指针是ListNode** temp,您使用(*temp)=new ListNode(x)分配新节点并使用temp=&(*temp)->next前进到下一个(前任)位置。如果您更喜欢使用虚拟节点,则可以使用ListNode* temp=&dummy;并使用temp->next=new ListNode(x)分配新节点,并在您的逻辑位置超出该节点之后仅使用temp=temp->next前进。

根据您的评论进行修改。如果你想避免双指针的语法(不是现实):

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {

        ListNode dummy = ListNode(0);
        ListNode * temp = &dummy;
        int carry =0;

        while(l1!=NULL || l2!=NULL)
        {
            if (l1!=NULL)
            {
                 carry += l1->val;
                 l1 = l1->next;
            }
            if (l2!=NULL)
            {
                 carry += l2->val;
                 l2 = l2->next;
            }

            temp = temp->next = new ListNode(carry%10);
            carry /= 10;
        }

        if(carry==1) temp->next = new ListNode(1);

        return dummy.next;

    }

答案 2 :(得分:1)

这些部分是你的问题:

        temp = new ListNode(x);
        carry = (l1->val + l2->val + carry)/10;
        temp = temp->next;

您创建一个新的ListNode,然后使用temp = temp->next 忘记它。那时temp->nextNULL,你失去了访问先前创建的ListNode的能力,更不用说修改它的next指针。

重新开始。这被设计打破了。