[英]Runtime error in Linked List
我一直在使用鏈表(出於學習目的,使用class
)。 我決定這次使用friend
功能。 該程序生成2個鏈表對象,並調用friend void mergeAlternate(LL LL1, LL LL2);
功能。 ( LL
是我班的名字)
mergeAlternate
函數從鏈接列表中同時獲取節點並將其替換放置。 例如:
LL1:1-> 2-> 3
LL2:4-> 5-> 6
回答:1-> 4-> 2-> 5-> 3-> 6
這是我的代碼::
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
this->next = NULL;
}
};
class LL {
private:
Node *head;
public:
LL() : head(NULL) {
createLL();
}
void printLL(Node *head) {
if(head == NULL)
head = this->head;
Node *temp = head;
while (temp != NULL) {
cout << temp->data << "-->";
temp = temp->next;
}
cout << "NULL" << endl;
}
void createLL() {
head = new Node(2);
head->next = new Node(7);
head->next->next = new Node(8);
head->next->next->next = new Node(1);
head->next->next->next->next = new Node(4);
head->next->next->next->next->next = new Node(9);
}
friend void mergeAlternate(LL LL1, LL LL2);
~LL() {
Node *temp = NULL;
while (head != NULL) {
temp = head;
head = head->next;
delete temp;
}
}
};
void mergeAlternate(LL LL1, LL LL2) {
Node *head1 = LL1.head, *head2 = LL2.head;
Node *temp1, *temp2;
while ((head1 != NULL) && (head2 != NULL)) {
temp1 = head1->next;
temp2 = head2->next;
head1->next = head2;
head2->next = temp1;
if (temp1 == NULL)
break;
head1 = temp1;
head2 = temp2;
}
if (head2 != NULL) {
head1->next = head2;
}
LL2.head = NULL;
LL1.printLL(LL1.head);
}
int main() {
LL newLL, newLL2;
newLL2.printLL(NULL);
mergeAlternate(newLL, newLL2);
newLL2.printLL(NULL);
}
我有一個用於打印鏈接列表的printLL
函數。
問題是在我的mergeAlternate
我按值傳遞了2個鏈接列表。 因此,我希望鏈接列表newLL
和newLL2
保持不變。 但是,在main
,當我打印鏈接列表時,在執行mergeAlternate
之后,出現運行時錯誤,並且會打印類似的內容。
155672576-->155672672-->155672592-->155672688-->155672608-->155672704-->155672624-->155672720-->155672640-->155672736-->155672656-->NULL
雖然我希望相同的輸入鏈接列表可以再次打印。 為什么會這樣? 有什么我想念的嗎? 謝謝你的幫助 :)
ideone鏈接:: http://ideone.com/apRCTw
您的函數void mergeAlternate(LL LL1, LL LL2)
創建兩個新的局部變量LL
和LL2
,它們的成員head
也將指向newLL
和newLL2
分別指向的同一內存地址。 因為LL1
和LL2
是函數的局部變量,所以當函數結束時,將調用它們各自的析構函數。 根據您的析構函數定義:
~LL() {
Node *temp = NULL;
while (head != NULL) {
temp = head;
head = head->next;
delete temp;
}
}
它將取消分配LL1
和LL2
的Nodes
,但是因為它們與newLL
和newLL2
是相同的內存地址,這意味着當函數結束時,這最后兩個對象的成員head
和后續引用中將具有垃圾值,這將導致嘗試訪問其值時會導致錯誤。
我看到那里有一些陷阱。
您正在按值傳遞列表,包括它們的內部指針。 這意味着在函數內通過復制創建的列表指向與原始列表相同的數據結構。 因此,您在函數內所做的任何更改都將在原始列表中“看到”。
您做了列表的所謂“淺表副本”。 您沒有復制列表的內容。
要解決此問題,您需要對列表進行深層復制。 做一個創建列表副本的函數,或者在遍歷節點時創建節點的副本。 第一個解決方案可能是不太容易出錯。
您按值傳遞LL
,但是由於該類只是指向節點的指針的包裝器,因此實際上是傳遞了兩個指向各個列表的頭部的指針,並且由於您正在修改這些指針所指向的節點,因此與調用者的LL
實例使用的節點相同,您正在有效地修改調用者列表。只需考慮調用函數后應該有多少個不同的節點:
LL1: 1->2->3
LL2: 4->5->6
Ans: 1->4->2->5->3->6
這是LL1和LL2的3個節點的2乘以答案的6個,總共12個節點。 在構造LL1和LL2時,您分配了6個節點。
為了解決這個問題,您需要在合並列表時制作(分配)節點的副本,僅修改這些副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.