为什么我的基本优先级队列排序算法会导致 seg 错误
Why is my basic PriorityQueue sorting algorithm causing a seg fault?
我已经在这个链表优先级队列上工作了四五个小时,在我的一生中,我找不到这个 seg 错误的根源。这让我发疯了。
我知道问题的根源在于我的 swapUp() 函数(根据它们的优先级交换两个节点的位置),因为该列表在调用之前运行良好。seg 错误实际上不是由 swapUp() 引起的,而是由 peekAt() 引起的,它返回节点中位置 n 处的元素。但是除非首先调用 swapUp(),否则不会发生错误,所以这就是问题所在(我认为)。
析构函数中还存在一个 seg 错误,我相信这可能在 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 << "nnWARNING: Trying to dequeue empty queuenn";
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 << "nnWARNING: Trying to peek empty queuenn";
throw 3;
} else if( n < 0 || n > size){
std::cout << "nnWARNING: Trying to peek queue at non-existent index " << n << "nn";
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 << "nnWARNING: Trying to get priority from empty queuenn";
result = -1;
} else if( n < 0 || n > size){
std::cout << "nnWARNING: Trying to get priority from non-existent index " << n << "nn";
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 emptyn";
} else {
std::cout << "nINDEXtDATAtPRIORITYn";
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 emptyn";
} else {
std::cout << "nINDEXtDATAtPRIORITYn";
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 <<"nnALL DONEnn";
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;
}
这让我非常生气。这是一个如此基本的逻辑问题,我不知道为什么我会遇到这么多麻烦。任何帮助将不胜感激!
在swapUp
中,你有一些问题。 永远不会调用解决if(partner == head)
的子句,因为您已经返回了 if target == head。
swapUp
不会设置要交换的两个值的反向上一个和下一个指针,只会设置目标的next
和下一个节点的prev
。 上一个和下一个都需要交换以维护您的双向链表。
相关文章:
- C++ - 将元素按升序插入数组的 SEG 错误
- 为什么我在使用 istream 迭代器时会出现 seg 错误?
- 字符串上的合并排序上的 Seg 错误
- 导致 Seg 错误的 SingleLinkedList 的析构函数
- g++ 9.2.1 (Linux) 会导致 seg 错误,但 Windows 上的代码块不会
- 函数抛出seg错误,我不知道为什么
- Microsoft Visual Studio 2019交叉编译CMake库 - 有效,但存在SEG错误
- 由于相同的文件名/类名存在于不同的SO中而导致的SEG错误
- 尝试访问 3D 矢量中的元素时出现 Seg 错误
- 垫子对象数组太大会导致 Seg 错误
- 为什么push_back成矢量<矢量<int>>导致 seg 错误?
- 在向量中存储字符串存在 SEG 错误
- 更改本地类名时出现 seg 错误
- 使用 ->GetString( " ") 时出现 Seg 错误,它位于单独的类中
- 将字符数组转换为 std::string 以传递到 std::bitset seg 错误
- 字符和 int 连接何时会导致 seg 错误?
- 静态数组溢出堆栈(seg 错误 11)仅在类定义内部时,否则不会..?
- .EOF 在读取文件时导致 Seg 错误:FIXXED
- 在 qt5 中使用 QSharedPointer 时出现 Seg 错误
- 为什么我的 if 语句会出现 seg 错误?