2017-06-23 111 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; 
} 

我希望这能解决问题。

相关问题