【问题标题】: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);
}

【问题讨论】:

  • 您可以通过点击分数下方的灰色复选标记来接受答案。

标签: c++ linked-list mergesort divide-and-conquer


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2011-08-15
    • 2020-05-24
    • 2016-08-11
    相关资源
    最近更新 更多