合并链表上的排序

Merge sort on linked lists

本文关键字:排序 链表 合并      更新时间:2023-10-16

我正在尝试对链表进行合并排序。

我保持我的头变量全局并应用基本算法,即分而治之。

我不明白为什么我会遇到分段错误。

我知道我可以通过传递头部作为参考来做到这一点,但我仍然需要知道为什么会发生这种情况。

#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *next;
};
Node *head;
void push(Node **head_ref, int x) {
Node *temp = new Node();
temp->next = *head_ref;
temp->data = x;
*head_ref = temp;
}
void split(Node *temp, Node **a, Node **b) {
Node *slow;
Node *fast;
slow = temp;
fast = temp->next;
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
*a = temp;
*b = slow->next;
slow->next = NULL;
}
Node *mergesort(Node *a, Node *b) {
if (a == NULL) {
return b;
} else
if (b == NULL) {
return a;
}
if (a->data < b->data) {
a->next = mergesort(a->next, b);
return a;
} else {
b->next = mergesort(a, b->next);
return b;
}
}  
void merge(Node **head_ref) {
Node *head = *(head_ref);
Node *a;
Node *b;
if (head == NULL || head->next == NULL) {
return;
}
split(head, &a, &b);
merge(&a);
merge(&b);
head = mergesort(a, b);
}
void print(Node *n) {
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}
}

我的主要方法如下:

int main() {
Node *head;
push(&head, 1);
push(&head, 3);
push(&head, 6);
push(&head, 4);
push(&head, 2);
print(head);
merge(&head);
cout << endl;
print(head);
}

代码中有一些简单的错误:

  • head被定义为全局变量,但在main中也被定义为局部变量,所以这个局部变量在main内部使用,而不是全局变量。确实不需要全局变量。

  • main()中的局部变量Node *head;未初始化。所有push调用都将成功,构造一个由head指向的列表,但在1之后next节点有一个未定义的指针,print尝试取消引用此指针时将崩溃。行为未定义,您可能偶然出现在head中空指针,但您可能具有无效指针,从而导致未定义的行为。将head初始化为NULL

    Node *head = NULL;
    
  • merge结束时,你不会通过head_ref更新头部指针,所以调用方中的变量不会更新。写这个:

    *head_ref = mergesort(a, b);
    

请注意,merge接收Node *head指针并返回更新的Node *头指针会更简单。

另请注意,您的函数名称令人困惑:merge应该命名为mergesort,反之亦然。

这是一个修改版本:

#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *next;
};
void push(Node **head_ref, int x) {
Node *temp = new Node();
if (temp) {
temp->next = *head_ref;
temp->data = x;
*head_ref = temp;
}
}
void split(Node *temp, Node **a, Node **b) {
Node *slow = temp;
Node *fast = temp->next;
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
*a = temp;
*b = slow->next;
slow->next = NULL;
}
Node *merge(Node *a, Node *b) {
if (a == NULL) {
return b;
}
if (b == NULL) {
return a;
}
if (a->data <= b->data) {
a->next = merge(a->next, b);
return a;
} else {
b->next = merge(a, b->next);
return b;
}
}  
Node *mergesort(Node *head) {
Node *a;
Node *b;
if (head == NULL || head->next == NULL) {
return head;
}
split(head, &a, &b);
a = mergesort(a);
b = mergesort(b);
return merge(a, b);
}
void print(const Node *n) {
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}
count << endl;
}
int main() {
Node *head = NULL;
push(&head, 1);
push(&head, 3);
push(&head, 6);
push(&head, 4);
push(&head, 2);
print(head);
head = mergesort(head);
print(head);
return 0;
}