我有一个链接列表的合并实现。它接受List类型的两个参数,它是一个包含Node* head
指针和由Node
和typename T data
组成的结构Node* next
的类。我遇到的问题是我的实现不是应该连接节点,或者我可能只是错了。它需要做的是,如果你list1.merge(list2, list3);
,那么list1将成为list2和list3节点的组合。我需要通过指针操作来执行此操作并且不需要新的内存分配,因此将修改list2和list3。这就是我现在所拥有的:
template <typename T>
void List<T>::merge(List& list1, List& list2) {
typename List<T>::Node* list1Ptr = list1.head;
typename List<T>::Node* list2Ptr = list2.head;
for(;;) {
if (list1Ptr == NULL && list2Ptr != NULL) {
list1Ptr = list2Ptr->next;
head = list1.head;
break;
}
else if (list2Ptr == NULL && list1Ptr != NULL) {
list2Ptr = list1Ptr->next;
head = list1.head;
break;
}
else if (list1Ptr == NULL && list2Ptr == NULL) {
head = list1.head;
break;
}
else if (list1Ptr != NULL && list2Ptr != NULL) {
if (list1Ptr->data > list2Ptr->data){
typename List<T>::Node* temp;
temp = list2Ptr->next;
list1Ptr->next = list1Ptr;
list2Ptr = temp;
}
else if (list1Ptr->data < list2Ptr->data) {
typename List<T>::Node* temp;
temp = list1Ptr->next;
list1Ptr->next = list2Ptr;
list1Ptr = temp;
}
else if (list1Ptr->data == list2Ptr->data) {
list1Ptr = list1Ptr->next;
}
}
}
}
节点中包含的数据是为我们提供的类类型,它包含我们需要的所有正确的重载操作符。整个代码运行得很好,直到main超出范围,析构函数被调用剩下的东西,然后我得到一个Debug Assertion Failed Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
。
我真的不确定如何解决这个问题,我已经多次抽出它,这对我来说似乎都有意义。如果有人有任何提示让我朝着正确的方向前进,我将非常感激。谢谢大家的期待!
答案 0 :(得分:1)
这不能按预期工作:
list1Ptr->data > list2Ptr->data && list1Ptr != NULL
&& list2Ptr != NULL
在解除引用之前,您需要检查指针是否为NULL,否则您将获得未定义的行为。 (这意味着任何事情都可能发生,非常糟糕。) 此外,您应该使用nullptr而不是NULL。
然而,这不是错误消息的原因,因为您已检查其他条件中的所有NULL情况。
您的问题可能是建议的斜体。如果您想要评论,请告诉我们其余的代码。
答案 1 :(得分:1)
对于初学者来说,这里有些不对劲:
if (list1Ptr == NULL && list2Ptr != NULL) {
list1Ptr = list2Ptr;
head = list1.head;
break;
}
如果你完成遍历list1,那么你想要的是将list1的最后一个节点指向list2。
list1Ptr = list2Ptr;
什么都不做。它只是改变局部变量的值
这一部分也是如此:
else if (list2Ptr == NULL && list1Ptr != NULL) {
list2Ptr = list1Ptr;
head = list1.head;
break;
}
做事不好:
list1Ptr->data > list2Ptr->data && list1Ptr != NULL
&& list2Ptr != NULL
如果list1Ptr变为NULL,那么如果你试图访问NULL-&gt;数据肯定会有麻烦(因为通常表达式将从左到右执行)。
也:
else if (list1Ptr->data > list2Ptr->data && list1Ptr != NULL
&& list2Ptr != NULL) {
typename List<T>::Node* temp = list2Ptr;
list2Ptr = list2Ptr->next;
temp->next = list1Ptr;
}
这里也有一些问题。您首先将list2ptr存储在temp中。然后将list2ptr移动到list2中的下一个节点。但为什么要temp->next = list1ptr
?
你应该重新思考这一部分。对于下一个其他区块也是如此
最好的。
编辑:
好吧,让我们看看还能做些什么:
这是我建议您使用的伪代码:
func(list1,list2):
ptr1 = list1.head
ptr2 = list2.head
declare pointer curr
if(ptr1!= NULL and ptr2!=NULL){
if(ptr1->data < prt2->data)
{curr = ptr1
ptr1 = ptr1->next
head = curr
}
else{
curr = ptr2
ptr1 = ptr2->next
head = curr}}
else{
head = whichever one is not NULL, or NULL if both of them are and return
}
while(ptr1 != NULL and ptr2!=NULL){
if(ptr1->data < ptr2->data){
curr->next = ptr1
curr = ptr1
ptr1 = ptr1->next
continue}
else{
curr->next = ptr2
curr = ptr2
ptr2 = ptr2->next
continue}
}
if(ptr1 == NULL)
curr->next = ptr2
else
curr->next = ptr1