链表入队和出队
Linked List Enqueue and Dequeue
我的 enqueue 和 dequeue 对于使用 c++ 实现的链表 queue 有点麻烦。我的老师说模板是禁止使用的,我不能更改他给我们的 public 和私有函数。我不断收到分段错误。我真的不明白我做错了什么。我也包含了 header 和 enqueue 以及 dequeue 函数。
Header
const int MAX_STRING = 6;
typedef char Element300[MAX_STRING + 1];
class Queue300
{
public:
Queue300();
Queue300(Queue300&);
~Queue300();
void enQueue300(const Element300);
void deQueue300(Element300);
void view300();
private:
struct Node300;
typedef Node300 * NodePtr300;
struct Node300
{
Element300 element;
NodePtr300 next;
};
NodePtr300 front, rear;
};
入队
void Queue300::enQueue300(const Element300 input)
{
NodePtr300 temp = NULL;
temp = new (std::nothrow) Node300;
if (temp == NULL)
{
cerr << "The queue is full, could not add(enqueue) any more elements." << endl;
}
else if (front == NULL && rear == NULL)
{
strcpy(temp->element, input);
rear = temp;
rear->next = NULL;
front = rear;
temp = NULL;
}
else
{
strcpy(temp->element, input);
temp = rear->next;
rear = temp;
rear->next = NULL;
temp = NULL;
}
}
德queue
void Queue300::deQueue300(Element300 input)
{
NodePtr300 temp = NULL;
if (rear == NULL && front == NULL)
{
cerr << "The queue is already empty, could not delete(dequeue) any more elements." << endl;
}
else if (front == rear)
{
strcpy(temp->element, input);
temp = front;
delete temp;
temp = NULL;
front = NULL;
rear = NULL;
}
else
{
strcpy(temp->element, input);
temp = front;
front = front->next;
temp->next = NULL;
delete temp;
temp = NULL;
}
}
让我们来看看Enqueue:
if (temp == NULL)
{
...
}
else if (front == NULL && rear == NULL)
{
...
}
else
{
strcpy(temp->element, input); // copy input into temp->element
// temp points to rear->next (it is always NULL, isn't it?)
// we lost the Node300 previously pointed by temp.
temp = rear->next;
// rear points to the same location as temp (NULL)
rear = temp;
// rear->next: dereferencing NULL /!\
rear->next = NULL;
temp = NULL;
}
ASCII 艺术的时间到了。这是入队前:
REAR -------------------
|
v
[0]--> ... -->[N]-->NULL
^
FRONT ---|
您分配了一个节点 [X]
,被 temp
引用:
temp --> [X]
REAR 的 next 必须指向同一个节点:
REAR
|
v
[N] --> [X]
^
|
temp
然后,REAR 必须更新为引用 [X]
。
就指针操作而言,您甚至不需要 temp
指针,但让我们保留它,因为您正在检查之前是否正确分配了节点,这很好。
rear->next = temp;
rear = temp; // or rear = rear->next;
temp->next = NULL; // or rear->next = NULL;
另请注意,您在两个 else
分支中都执行了 strcpy(temp->element, input);
。您可以在 temp == NULL
时从函数中 return 并在检查 front
和 rear
是否为 NULL 之前进行复制。
在入队中,当您说 "temp = rear->next" 时,您将在临时中覆盖指向新节点的指针。
在向链表中添加新节点时,通常最好先在新节点中设置指针:
temp->next = null;
rear->next = temp;
rear=temp;
另外:
报错后,还得return。如果你继续下去,你会崩溃的。最好抛出一个异常或者return一个错误码
dequeue中的strcpys走错了路
为了防止缓冲区溢出,您应该真正使用 strncpy 而不是 strcpy,然后确保目标以 null 终止,因为 Element 应该是一个字符串
我的 enqueue 和 dequeue 对于使用 c++ 实现的链表 queue 有点麻烦。我的老师说模板是禁止使用的,我不能更改他给我们的 public 和私有函数。我不断收到分段错误。我真的不明白我做错了什么。我也包含了 header 和 enqueue 以及 dequeue 函数。
Header
const int MAX_STRING = 6;
typedef char Element300[MAX_STRING + 1];
class Queue300
{
public:
Queue300();
Queue300(Queue300&);
~Queue300();
void enQueue300(const Element300);
void deQueue300(Element300);
void view300();
private:
struct Node300;
typedef Node300 * NodePtr300;
struct Node300
{
Element300 element;
NodePtr300 next;
};
NodePtr300 front, rear;
};
入队
void Queue300::enQueue300(const Element300 input)
{
NodePtr300 temp = NULL;
temp = new (std::nothrow) Node300;
if (temp == NULL)
{
cerr << "The queue is full, could not add(enqueue) any more elements." << endl;
}
else if (front == NULL && rear == NULL)
{
strcpy(temp->element, input);
rear = temp;
rear->next = NULL;
front = rear;
temp = NULL;
}
else
{
strcpy(temp->element, input);
temp = rear->next;
rear = temp;
rear->next = NULL;
temp = NULL;
}
}
德queue
void Queue300::deQueue300(Element300 input)
{
NodePtr300 temp = NULL;
if (rear == NULL && front == NULL)
{
cerr << "The queue is already empty, could not delete(dequeue) any more elements." << endl;
}
else if (front == rear)
{
strcpy(temp->element, input);
temp = front;
delete temp;
temp = NULL;
front = NULL;
rear = NULL;
}
else
{
strcpy(temp->element, input);
temp = front;
front = front->next;
temp->next = NULL;
delete temp;
temp = NULL;
}
}
让我们来看看Enqueue:
if (temp == NULL)
{
...
}
else if (front == NULL && rear == NULL)
{
...
}
else
{
strcpy(temp->element, input); // copy input into temp->element
// temp points to rear->next (it is always NULL, isn't it?)
// we lost the Node300 previously pointed by temp.
temp = rear->next;
// rear points to the same location as temp (NULL)
rear = temp;
// rear->next: dereferencing NULL /!\
rear->next = NULL;
temp = NULL;
}
ASCII 艺术的时间到了。这是入队前:
REAR -------------------
|
v
[0]--> ... -->[N]-->NULL
^
FRONT ---|
您分配了一个节点 [X]
,被 temp
引用:
temp --> [X]
REAR 的 next 必须指向同一个节点:
REAR
|
v
[N] --> [X]
^
|
temp
然后,REAR 必须更新为引用 [X]
。
就指针操作而言,您甚至不需要 temp
指针,但让我们保留它,因为您正在检查之前是否正确分配了节点,这很好。
rear->next = temp;
rear = temp; // or rear = rear->next;
temp->next = NULL; // or rear->next = NULL;
另请注意,您在两个 else
分支中都执行了 strcpy(temp->element, input);
。您可以在 temp == NULL
时从函数中 return 并在检查 front
和 rear
是否为 NULL 之前进行复制。
在入队中,当您说 "temp = rear->next" 时,您将在临时中覆盖指向新节点的指针。
在向链表中添加新节点时,通常最好先在新节点中设置指针:
temp->next = null;
rear->next = temp;
rear=temp;
另外:
报错后,还得return。如果你继续下去,你会崩溃的。最好抛出一个异常或者return一个错误码
dequeue中的strcpys走错了路
为了防止缓冲区溢出,您应该真正使用 strncpy 而不是 strcpy,然后确保目标以 null 终止,因为 Element 应该是一个字符串