链表上的合并排序
Posted
技术标签:
【中文标题】链表上的合并排序【英文标题】:Merge sort on linked lists 【发布时间】:2020-09-25 12:11:38 【问题描述】:我正在尝试对链表进行合并排序。
我将 head 变量保持为全局变量并应用基本算法,即分而治之。
我不明白为什么会出现分段错误。
我知道我可以通过传递 head 作为参考来做到这一点,但我仍然需要知道为什么会这样。
#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);
【问题讨论】:
您可以通过点击分数下方的灰色复选标记来接受答案。 【参考方案1】:您的代码中有一些简单的错误:
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;
【讨论】:
以上是关于链表上的合并排序的主要内容,如果未能解决你的问题,请参考以下文章
合并两个排序的链表使之依然有序(不开辟新空间在原链表上操作的非递归版本)
Leetcode练习(Python):链表类:第23题:合并K个排序链表:合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。