2017-06-23 100 views
0

我想通過在C++中使用鏈表來實現優先級隊列。但是,當我運行該程序時,它會在「priorityQLinkedList :: dequeue()」方法內觸發一個斷點。有人可以告訴我們爲什麼會出現這種情況,並告訴我如何解決這個問題?我得到一個斷點,我不知道爲什麼

代碼:

#include <iostream> 
#include <cstring> 
#include <iomanip> 

using namespace std; 

struct DAT 
{ 
    int id; 
    char fullname[50]; 
    double savings; 
}; 

struct NODE 
{ 
    DAT data; 
    NODE *N; 
    NODE *P; 
    NODE(const int i, const char *f, const double s) 
    { 
     data.id = i; 
     strcpy_s(data.fullname, f); 
     data.savings = s; 
     N = NULL; 
     P = NULL; 
    } 
}; 

class priorityQLinkedList 
{ 
private: 
    NODE *front; 
    NODE *back; 
public: 
    priorityQLinkedList() { front = NULL; back = NULL; } 
    ~priorityQLinkedList() { destroyList(); } 
    void enqueue(NODE *); 
    NODE* dequeue(); 
    void destroyList(); 
}; 

void priorityQLinkedList::enqueue(NODE *n) 
{ 
    if (front == NULL) { 
     front = n; 
     back = n; 
    } 

    else { 
     NODE *temp = front; 
     if (n->data.id > temp->data.id) 
     { 
      front->P = n; 
      n->N = front; 
      front = n; 
     } 
     else 
     { 
      //search for the posistion for the new node. 
      while (n->data.id < temp->data.id) 
      { 
       if (temp->N == NULL) { 
        break; 
       } 
       temp = temp->N; 
      } 

      //New node id's smallest then all others 
      if (temp->N == NULL && n->data.id < temp->data.id) 
      { 
       back->N = n; 
       n->P = back; 
       back = n; 
      } 

      //New node id's is in the medium range. 
      else { 
       temp->P->N = n; 
       n->P = temp->P; 
       n->N = temp; 
       temp->P = n; 
      } 
     } 
    } 
} 

NODE* priorityQLinkedList::dequeue() 
{ 
    NODE *temp; 

    //no nodes 
    if (back == NULL) { 
     return NULL; 
    } 

    //there is only one node 
    else if (back->P == NULL) { 
     NODE *temp2 = back; 
     temp = temp2; 
     front = NULL; 
     back = NULL; 
     delete temp2; 
     return temp; 
    } 

    //there are more than one node 
    else { 
     NODE *temp2 = back; 
     temp = temp2; 
     back = back->P; 
     back->N = NULL; 
     delete temp2; 
     return temp; 
    } 

} 

void priorityQLinkedList::destroyList() 
{ 
    while (front != NULL) { 
     NODE *temp = front; 
     front = front->N; 
     delete temp; 
    } 
} 

void disp(NODE *m) { 
    if (m == NULL) { 
     cout << "\nQueue is Empty!!!" << endl; 
    } 
    else { 
     cout << "\nID No. : " << m->data.id; 
     cout << "\nFull Name : " << m->data.fullname; 
     cout << "\nSalary : " << setprecision(15) << m->data.savings << endl; 
    } 
} 

int main() { 
    priorityQLinkedList *Queue = new priorityQLinkedList(); 

    NODE No1(101, "Qasim Imtiaz", 567000.0000); 
    NODE No2(102, "Hamad Ahmed", 360200.0000); 
    NODE No3(103, "Fahad Ahmed", 726000.0000); 
    NODE No4(104, "Usmaan Arif", 689000.0000); 

    Queue->enqueue(&No4); 
    Queue->enqueue(&No3); 
    Queue->enqueue(&No1); 
    Queue->enqueue(&No2); 

    disp(Queue->dequeue()); 
    disp(Queue->dequeue()); 
    disp(Queue->dequeue()); 
    disp(Queue->dequeue()); 
    disp(Queue->dequeue()); 

    delete Queue; 
    return 0; 
} 
+1

糾正我,如果我錯了,但如果你刪除節點出隊,然後返回一個指向相同的指針,這不會給調用者帶來問題,然後誰會回來一個「死」指針? –

+0

@TimBiegeleisen這就是發生了什麼,你應該把它寫爲答案 –

+0

@AndersK。我嘗試了下面的答案。我沒有看到處理這個問題的好方法,但我想''dequeue()'應該是刪除目標節點。我的答案是複製'NODE'並返回給調用者。但是那時調用者必須在某個時候調用'delete'。 –

回答

1

的一個問題,其在dequeue()方法突出的是,你是在NODE指針調用delete,然後試圖返回這個刪除指針給調用者。這可能會導致在dequeue()本身發生錯誤,或者肯定在調用者認爲他正在取回指向實際的對象的指針的錯誤。

一個可能的修復方法是創建NODE的出列副本。你仍然會從你的列表中刪除目標,但是調用者會返回一個有效的指針,以後他可以釋放它。

NODE* priorityQLinkedList::dequeue() 
{ 
    NODE *temp; 

    // no nodes 
    if (back == NULL) { 
     return NULL; 
    } 

    NODE *temp2 = back; 
    temp = new NODE(temp2->data.id, temp2->data.fullname, temp2->data.savings); 

    // there is only one node 
    else if (back->P == NULL) { 
     front = NULL; 
     back = NULL; 
     delete temp2; 
     return temp; 
    } 

    // there are more than one node 
    else { 
     back = back->P; 
     back->N = NULL; 
     delete temp2; 
     return temp; 
    } 
} 
+0

你假設'priorityQLinkedList'擁有節點指針。它不是。它們被傳入'enqueue'並由'enqueue'的調用者擁有。這個解決方案不能解決OP的問題。 – 1201ProgramAlarm

+0

@ 1201ProgramAlarm請編輯我的答案並加以解決。我不是一個C++大師,但是返回一個已刪除的指針對我來說有異味。希望我更瞭解C++。 –

1

你刪除的dequeuepriorityQLinkedList不擁有指針,所以你不知道這是否是安全的刪除它們。

在這種情況下,它們不是,因爲傳遞給enqueue的節點指針是本地堆棧基變量的地址,並且沒有被new分配。 (還有已經提到的刪除指針然後返回它的問題,這是未定義行爲。)

所示代碼的修復程序是在dequeue中刪除對delete的調用。但是,如果進行更改以便傳遞到enqueue的節點是動態分配的,則需要添加一些內容來處理該問題。

1

1.首先將strcpy改爲strcpy爲struct NODE。

2.替代刪除(temp2)使用temp2--。

//no nodes 
if (back == NULL) { 
    return NULL; 
} 

//there is only one node 
else if (back->P == NULL) { 
    NODE *temp2 = back; 
    temp = temp2; 
    front = NULL; 
    back = NULL; 
    temp2--; 
    return temp; 
} 

//there are more than one node 
else { 
    NODE *temp2 = back; 
    temp = temp2; 
    back = back->P; 
    back->N = NULL; 
    temp2--; 
    return temp; 
} 

我希望這能解決問題。

相關問題