簡體   English   中英

合並兩個排序的列表出現運行時錯誤

[英]Merge Two Sorted Lists got RUNTIME ERROR

這是我針對Leetcode的“合並兩個排序列表”算法問題的代碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *dummy, *pre;
        dummy->next = l1;
        pre = dummy;
        while(l1 != NULL & l2 != NULL) {
            if(l1->val < l2->val) {
                pre = l1;
                l1 = l1->next;
            } else {
                pre->next = l2;
                l2->next = l1;
                pre = l2;
                l2 = l2->next;
            }
        }
        if(l2 != NULL) {
            pre->next = l2;
        }
        return dummy->next;

    }
};

而且我遇到了運行時錯誤 但是我的代碼有什么問題?

我相信正確的實現將需要比OP中更多的代碼。 這是一個可以嘗試的正確實現。 我假設輸入列表l1l2按降序排序(即從頭到尾從大到最小)。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *pnt1 = l1;
        ListNode *pnt2 = l2;
        ListNode *head;

        // assign the head pointer to larger head of the two input lists
        if (l1->val > l2->val) {
            head = l1;
        }
        else {
            head = l2;
        }

        // walk through both lists sequentially,
        // and splice together the sorted list
        while (pnt1->next != NULL & pnt2->next != NULL) {
            if(pnt2->val > pnt1->next->val && pnt1->val > pnt2->val) {
                ListNode* next = pnt1->next;
                pnt1->next = pnt2;
                pnt1 = next;
            }
            else if(pnt2->val > pnt1->next->val && pnt1->val <= pnt2->val) {
                ListNode* next = pnt2->next;
                pnt2->next = pnt1;
                pnt2 = next;
            }
            else if(pnt2->val <= pnt1->next->val && pnt1->val > pnt2->val) {
                pnt1 = pnt1->next;
            }
        }

        // handle edge case where end of one or two list(s) has been reached
        if (pnt1->next == NULL && pnt2->next == NULL) {
            if (pnt1->val > pnt2->val) {
                pnt1->next = pnt2;
            }
            else {
                pnt2->next = pnt1;
            }
        }
        else if (pnt1->next == NULL) {
            while (pnt2->next != NULL) {
                if (pnt1->val > pnt2->next->val) {
                    ListNode* next = pnt2->next;
                    pnt2->next = pnt1;
                    pnt1->next = next;
                    break;
                }
                pnt2 = pnt2->next;
            }
            if (pnt2->next == NULL) {
                pnt2->next = pnt1;
            }
        }
        else if (pnt2->next == NULL) {
            while (pnt1->next != NULL) {
                if (pnt2->val > pnt1->next->val) {
                    ListNode* next = pnt1->next;
                    pnt1->next = pnt2;
                    pnt2->next = next;
                    break;
                }
                pnt1 = pnt1->next;
            }
            if (pnt1->next == NULL) {
                pnt1->next = pnt2;
            }
        }

        return head;
    }
};

我認為您遇到了Segmentation Fault(Core Dump)因為您嘗試訪問無效的內存:

dummy->next = l1;

在訪問它們的成員之前,應該為*dummy*pre分配內存。

還可以在循環中使用&& (邏輯運算符)代替& (按位運算符)。 更換:

while(l1 != NULL & l2 != NULL) {

while(l1 != NULL && l2 != NULL) {

使用new運算符分配內存,請使用delete釋放內存並避免內存泄漏。

還要注意,實現本身在邏輯上是錯誤的。 請參考此處以獲得更好的實現。

這是一個簡單的遞歸實現:

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { 
{
  ListNode* result = NULL;

  /* Base cases */
  if (l1 == NULL) 
     return (l2);
  else if (l2 == NULL) 
     return (l1);

  if (l1->data <= l2->data) 
  {
     result = l1;
     result->next = mergeTwoLists(l1->next, l2);
  }
  else
  {
     result = l2;
     result->next = mergeTwoLists(l1, l2->next);
  }
  return(result);
}

您的代碼中的主要問題是您正在使用:

    dummy->next = l1;

dummy尚未初始化為指向有效對象時。

您還使用按位& ,其中邏輯&&適當。

    while(l1 != NULL & l2 != NULL) {

這是建議的實現。

PS尚未經過測試,但對我來說似乎正確。

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

   ListNode* ret = NULL;
   ListNode* pre = NULL;

   // Make sure the start of the list to be returned points to the right
   // ListNode.
   if ( l1 != NULL && l2 != NULL )
   {
      if ( l1->val < l2->val )
      {
         ret = l1;
         l1 = l1->next;
      }
      else
      {
         ret = l2;
         l2 = l2->next;
      }
   }
   else if ( l1 != NULL )
   {
      return l1;
   }
   else
   {
      return l2;
   }

   pre = ret;

   while(l1 != NULL && l2 != NULL) {

      // Figure out where pre->next must point to.
      // Advance l1 and l2 appropriately.
      if(l1->val < l2->val) {
         pre->next = l1;
         pre = l1;
         l1 = l1->next;
      } else {
         pre->next = l2;
         pre = l2;
         l2 = l2->next;
      }
   }

   // Make sure pre->next points to the remaining ListNodes.
   // They could be in l1 or l2.
   if ( l1 != NULL )
   {
      pre->next = l1;
   }

   if( l2 != NULL)
   {
      pre->next = l2;
   }

   return ret;
}

除了已經指出的問題外,原始代碼無法處理首先到達列表2末尾的情況,在這種情況下,列表1的其余部分應附加到合並列表中。 使用指向指針的指針(而不是先前的指針)可使代碼更簡單。 這是合並兩個列表的示例代碼,以及使用合並列表功能的自底向上合並排序。 排序使用一個指向列表的指針數組,其中array [i]為null或指向其中包含pow(2,i)元素的列表。

ListNode * MergeLists(ListNode *pl1, ListNode *pl2)
{
ListNode *plm = NULL;                   /* merged list head ptr */
ListNode **pplm = &plm;                 /* ptr to head or prev->next */
    if(pl1 == NULL)
        return pl2;
    if(pl2 == NULL)
        return pl1;
    while(1){
        if(pl2->val < pl1->val){        /* if src2 < src1 */
            *pplm = pl2;
            pl2 = *(pplm = &(pl2->next));
            if(pl2 == NULL){
                *pplm = pl1;
                break;
            }
        } else {                        /* src1 <= src2 */
            *pplm = pl1;
            pl1 = *(pplm = &(pl1->next));
            if(pl1 == NULL){
                *pplm = pl2;
                break;
            }
        }
    }
    return plm;
}

#define NUMLISTS 32                     /* number of lists */
ListNode * SortList(ListNode *pList)
{
ListNode * aList[NUMLISTS];             /* array of lists */
ListNode * pNode;
ListNode * pNext;
int i;
    if(pList == NULL)                   /* check for empty list */
        return NULL;
    for(i = 0; i < NUMLISTS; i++)       /* zero array */
        aList[i] = NULL;
    pNode = pList;                      /* merge nodes into aList[] */
    while(pNode != NULL){
        pNext = pNode->next;
        pNode->next = NULL;
        for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
            pNode = MergeLists(aList[i], pNode);
            aList[i] = NULL;
        }
        if(i == NUMLISTS)
            i--;
        aList[i] = pNode;
        pNode = pNext;
    }
    pNode = NULL;                       /* merge array into one list */
    for(i = 0; i < NUMLISTS; i++)
        pNode = MergeLists(aList[i], pNode);
    return pNode;
}

暫無
暫無

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

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