Я реализовал проблему слияния отсортированного массива в C++ и обнаружил, что в моем коде произошло что-то странное. Итак, вот мой код.
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x): val(x), next(NULL) {}
};
class Solution {
public:
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
if (l1 == NULL)
return l2;
else if (l2 == NULL)
return l1;
else
{
ListNode *head, *p;
ListNode *h1 = l1;
ListNode *h2 = l2;
if (h1->val <= h2->val)
{
ListNode newNode(h1->val);
head = &newNode;
h1 = h1->next;
}
else
{
ListNode newNode(h2->val);
head = &newNode;
h2 = h2->next;
}
p = head;
while (h1 != NULL && h2 != NULL)
{
if (h1->val <= h2->val)
{
ListNode *Node = new ListNode(h1->val);
p->next = Node;
//p = p->next;
h1 = h1->next;
}
else
{
ListNode *Node = new ListNode(h2->val);
p->next = Node;
//p = p->next;
h2 = h2->next;
}
p = p->next;
}
if (h2 != NULL)
{
while (h2 != NULL)
{
ListNode *Node = new ListNode(h2->val);
p->next = Node;
p = p->next;
h2 = h2->next;
}
}
else if (h1 != NULL)
{
while (h1 != NULL)
{
ListNode *Node = new ListNode(h1->val);
p->next = Node;
p = p->next;
h1 = h1->next;
}
}
return head;
}
}
};
int main()
{
ListNode A1(1);
ListNode A2(2);
ListNode A3(3);
ListNode A4(5);
ListNode A5(7);
A1.next = &A2;
A2.next = &A3;
A3.next = &A4;
A4.next = &A5;
ListNode B1(2);
ListNode B2(4);
ListNode B3(6);
ListNode B4(8);
ListNode B5(10);
B1.next = &B2;
B2.next = &B3;
B3.next = &B4;
B4.next = &B5;
Solution solution;
ListNode *x = solution.mergeTwoLists(&A1, &B1);
while (x != NULL)
{
cout << x->val << endl;
x = x->next;
}
return 0;
}
Этот код получит ошибку времени выполнения. Когда я отлаживал его в кодовых блоках, я обнаружил, что все нормально в классе Solution. Когда дело доходит до основной функции, цикл while, что-то ненормальное произошло! x указывает на какой-то странный адрес после одного цикла. Мне интересно, что случилось.
Здесь, в mergeTwoLists
:
if (h1->val <= h2->val)
{
ListNode newNode(h1->val);
head = &newNode;
h1 = h1->next;
}
else
{
ListNode newNode(h2->val);
head = &newNode;
h2 = h2->next;
}
Все остальные узлы, которые вы создаете в куче с new
, но здесь вы создаете newNode
в стеке. Это первый узел списка, который вы создаете, и это локальная переменная mergeTwoLists
. Когда управление переходит из функции, этот первый узел выходит из области видимости. Затем к нему доступ и разыменования его next
с main
, что неопределенное поведение.
Попробуйте использовать это
while (x->next != NULL)
Первая проблема, которую я вижу в un jour code, заключается в том, что вы сохраняете адреса для стека выделенных переменных:
ListNode *head, *p;
// ...
if (h1->val <= h2->val) {
ListNode newNode(h1->val);
head = &newNode;
h1 = h1->next;
// newNode is destroyed here
// thus head now points to invalid
// data
} else {
// same kind of code
}
p = head;
// p does not point to anything useful
Это неправильно с вашим кодом.
Связанные списки, подобные тем, которые вы реализуете с помощью ListNode
, обычно реализуются с использованием динамически распределенных узлов. Вы также должны попробовать его здесь. Я предлагаю вам реализовать самые основные алгоритмы для вашего связанного списка (вставка, удаление, поиск) до слияния, таким образом, вы с большей вероятностью сможете нащупать эту структуру.