2014-11-15 2 views
-1

저는이 링크 된 목록 우선 순위 큐에서 4 시간에서 5 시간 정도 더 잘 작업했습니다. 그리고 저의 삶에서이 seg fault의 근원을 찾을 수 없습니다. 나를 미치게 만들었다.내 기본 PriorityQueue 정렬 알고리즘이 seg fault를 일으키는 이유는 무엇입니까?

나는이 호출 될 때까지 목록이 위대한을 작동하기 때문에 문제의 근본은, (우선 순위에 따라 두 노드의 위치를 ​​교환) 내 swapUp() 함수에 있음을 알고있다. seg 오류는 실제로 swapUp()에 의해 발생 된 것이 아니며 노드의 위치 n에있는 요소를 반환하는 peekAt()에 의해 발생합니다. 하지만 swapUp()이 먼저 호출되지 않으면 오류가 발생하지 않으므로 문제가있는 부분이됩니다 (생각합니다).

또한 내가() swapUp에서 같은 근본 원인이있을 수 있습니다 생각 소멸자에서 발생되는 독방 감금 잘못이있다.

나는 반복해서 코드를 통해 갔다 나는 밤새 디버깅 봤는데 난 그냥 잘못된 것입니다 정확히 알아낼 수 없습니다. 정말이 점에 대해 약간의 도움을 주시면 감사하겠습니다.

우선 순위 큐 :

#ifndef JMF_PriorityQueue 
#define JMF_PriorityQueue 

#include <iostream> 
#include <string> 

template <typename T> 
class PriorityQueue{ 
    public: 
     struct Node{ 
      T data; 
      int priority; 
      Node * next; 
      Node * prev; 
     }; 

    PriorityQueue(); 
    PriorityQueue & operator=(const PriorityQueue &rhs); 
    bool isEmpty();   //Returns true if queue is empty 
    int getLength();  //Returns length of queue 
    void enqueue(T data, int p); //Enqueues data T with priority p 
    void enqueue(T data);   //Enqueues data T with priority 1 
    T dequeue();     //Dequeues and returns data at head of queue 
    void clearQueue();    //Empties queue 
    T peek();      //Returns data at head of queue without dequeing it 
    T peekAt(int n);    //Returns data element n without dequeuing it 
    int getPriority(int n);   //Returns priority of item at position n 
    void display();     //Prints list of data elements to screen 
    void revDisplay(); 
    void swapUp(Node * target);  //Swaps target node with it's neighbor next in line 
    bool contains(T data);   //Returns true if data exists as an element anywhere on the queue 
    ~PriorityQueue(); 

    private: 
     int size; 
     Node * head, *tail; 
}; 

template <typename T> 
PriorityQueue<T>::PriorityQueue(){ 
    size = 0; 
    head = 0; 
    tail = 0; 
} 

template <typename T> 
PriorityQueue<T> & PriorityQueue<T>::operator=(const PriorityQueue &rhs){ 
    clearQueue(); 
    for(int n = 0; n < rhs.size(); n++) 
     enqueue(rhs.peekAt(n)); 
    return *this; 
} 

template <typename T> 
int PriorityQueue<T>::getLength(){ 
    return size; 
} 

template <typename T> 
bool PriorityQueue<T>::isEmpty(){ 
    return(!size); 
} 

template <typename T> 
void PriorityQueue<T>::enqueue(T data){ 
    enqueue(data, 1); 
} 

template <typename T> 
void PriorityQueue<T>::enqueue(T data, int p){ 
    Node * newNode = new Node(); 
    newNode -> data = data; 
    newNode -> priority = p; 

    if(isEmpty()){ 
     head = newNode; 
     tail = newNode; 
    } else { 
     newNode -> next = tail; 
     tail -> prev = newNode; 
     tail = newNode; 


     //WHEN THIS WHILE LOOP IS COMMENTED OUT (IE NO SORTING), NO SEG FAULT ISSUES 

     while(newNode != head && newNode->priority < newNode->next->priority) 
      swapUp(newNode); 

     std::cout << "\n"; 
    } 
    tail->prev = 0; 
    head->next = 0; 
    size++; 
} 

template <typename T> 
T PriorityQueue<T>::dequeue(){ 
    if(isEmpty()){ 
     std::cout << "\n\nWARNING: Trying to dequeue empty queue\n\n"; 
     throw 3; 
    } else { 
     Node * frontNode = head; 
     T result = frontNode -> data; 
     if(size == 1){ 
      head = 0; 
      tail = 0; 
     } else { 
      head = frontNode -> prev; 
      head -> next = 0; 
     } 
     delete frontNode; 
     size--; 
     return result; 
    } 
} 

template <typename T> 
void PriorityQueue<T>::clearQueue(){ 
    while(!isEmpty()) 
     dequeue(); 
} 

template <typename T> 
T PriorityQueue<T>::peek(){ 
    return peekAt(0); 
} 

template <typename T> 
T PriorityQueue<T>::peekAt(int n){ 
    T result; 
    Node * thisNode; 
    if(isEmpty()){ 
     std::cout << "\n\nWARNING: Trying to peek empty queue\n\n"; 
     throw 3; 
    } else if(n < 0 || n > size){ 
     std::cout << "\n\nWARNING: Trying to peek queue at non-existent index " << n << "\n\n"; 
     throw 3; 
    } else { 
     thisNode = head; 
     if(thisNode->prev == 0) 
     for(int k = 0; k < n; k++) 
      thisNode = thisNode -> prev; 
     result = thisNode -> data;    //Crashes program if swapUp() is ever called 
    } 
    return result; 
} 

template <typename T> 
int PriorityQueue<T>::getPriority(int n){ 
    int result; 
    if(isEmpty()){ 
     std::cout << "\n\nWARNING: Trying to get priority from empty queue\n\n"; 
     result = -1; 
    } else if(n < 0 || n > size){ 
     std::cout << "\n\nWARNING: Trying to get priority from non-existent index " << n << "\n\n"; 
     result = -1; 
    } else{ 
     Node * thisNode = head; 
     for(int k = 0; k < n; k++) 
      thisNode = thisNode -> prev; 
     result = thisNode -> priority; 
    } 
    return result; 
} 

template <typename T> 
void PriorityQueue<T>::display(){ 
    if(isEmpty()){ 
     std::cout << "\nQueue is empty\n"; 
    } else { 
     std::cout << "\nINDEX\tDATA\tPRIORITY\n"; 
     std::cout << "-----------------------\n"; 
     Node * thisNode = head; 
     for(int n = 0; n < size; n++){ 
      std::cout << n << "\t" << thisNode->data << "\t" << thisNode->priority << "\n"; 
      thisNode = thisNode -> prev; 
     } 
     std::cout << "\n"; 
    } 
} 


template <typename T> 
void PriorityQueue<T>::revDisplay(){ 
    if(isEmpty()){ 
     std::cout << "\nQueue is empty\n"; 
    } else { 
     std::cout << "\nINDEX\tDATA\tPRIORITY\n"; 
     std::cout << "-----------------------\n"; 
     Node * thisNode = tail; 
     for(int n = 0; n < size; n++){ 
      std::cout << n << "\t" << thisNode->data << "\t" << thisNode->priority << "\n"; 
      thisNode = thisNode -> next; 
     } 
     std::cout << "\n"; 
    } 
} 


template <typename T> 
void PriorityQueue<T>::swapUp(Node * target){ 
    if(target == head) 
     return; 

    Node * partner = target->next; 
    if(partner == head){ 
     head = target; 
     target->next = 0; 
    } else 
     target->next = partner->next; 
    if(target == tail){ 
     tail = partner; 
     partner->prev = 0; 
    } else 
     partner->prev = target->prev; 
} 

template <typename T> 
bool PriorityQueue<T>::contains(T data){ 
    bool result = false; 
    if(!isEmpty()){ 
     Node * thisNode = head; 
     for(int n = 0; n < size; n++){ 
      if(thisNode->data == data){ 
       result = true; 
       break; 
      } 
      thisNode = thisNode -> prev; 
     } 
    } 
    return result; 
} 

template <typename T> 
PriorityQueue<T>::~PriorityQueue(){ 
    clearQueue(); 
} 

#endif 

테스트 프로그램 :

#include <iostream> 
#include <string> 
#include <ctype.h> 
#include <cstring> 
#include <sstream> 
#include <cstdlib> 
#include "PriorityQueue.hpp" 

int main(){ 
     PriorityQueue<char> test; 
     test.enqueue('c',1); 
     test.enqueue('a',2); 
     test.enqueue('t',3); 
     test.display(); 
     std::cout <<"\nREVERSE:\n"; 
     test.revDisplay(); 
     std::cout<<"\nWITH SORTING:\n"; 
     test.enqueue('d',5); 
     test.enqueue('s',9); 
     test.enqueue('g',7); 
     test.enqueue('o',6); 
     test.enqueue('&',4); 
     test.display(); 
     std::cout <<"\n\nALL DONE\n\n"; 
     return 0; 
} 

좋아, 나는 아직도 나에게 오류를주는 둘 다 서로 다른 두 가지 새로운 방법에 SwapUp()를 구현하는 시도했습니다.

실패 시도 # 1 :

template <typename T> 
void PriorityQueue<T>::swapUp(Node * target){ 
    Node * partner = target->next; //Partner = target next 

    Node * temp = new Node; // temp spot to hold partner neighbors 

    temp->next = partner->next; 
    temp->prev = partner->prev; 

    partner->next = target->next; 
    partner->prev = target->prev; 

    target->next = temp->next; 
    target->prev = temp->prev; 

    if(target == tail) 
     tail = partner; 
    if(partner == head) 
     head = target; 

    delete temp; 
} 

실패 시도 # 2 :

template <typename T> 
void PriorityQueue<T>::swapUp(Node * target){ 
    Node * partner = target->next; //Partner = target next 

    target->next = partner->next; //Target next = partner next 
    partner->prev = target->prev; //Partner prev = target prev 
    partner->next = target;   //Partner next = target 
    target->prev = partner;   //Target prev = partner 

    if(target == tail) 
     tail = partner; 
    if(partner == head) 
     head = target; 

} 

이 나를 절대적으로 미친 운전. 이것은 내가 왜 그렇게 많은 문제를 겪고 있는지 모르는 초등 논리 문제입니다. 어떤 도움이라도 크게 대단히 감사하겠습니다!

답변

1

swapUp, 당신은 문제의 소수를 가지고있다. 주소가 if(partner == head) 인 절은 절대로 target == head 일 경우 이미 반환했기 때문에 호출되지 않습니다.

swapUp은 대상의 next 및 다음 노드의 prev 만 바꿔서 두 값의 역방향 이전 및 다음 포인터를 설정하지 않습니다. 귀하의 이중 연결 목록을 유지하기 위해 이전과 다음으로 교환해야합니다.

관련 문제