简体   繁体   English

合并排序到链表上

[英]Merge sort on a linked list

So I've been trying to sort a linked list using merge sort, I found this code and tried to work on it, but it doesn't seen to really work? 因此,我一直在尝试使用合并排序对链接列表进行排序,我找到了这段代码并尝试对其进行处理,但是它似乎没有真正起作用吗?

What could be the problem with it? 可能是什么问题? I'm not quite sure about the getMiddle method although I know it should get the middle value of the list in order to work on 2 lists from the list itself 我不太了解getMiddle方法,尽管我知道它应该获取列表的中间值才能处理列表本身中的2个列表

Here's the code; 这是代码;

public Node mergeSort(Node head) {

    if (head == null || head.link == null) {
        return head;       
    }

    Node middle = getMiddle(head);

    Node sHalf = middle.link;
    middle.link = null;       

    return merge(mergeSort(head), mergeSort(sHalf));
}

public Node merge(Node a, Node b) {
    Node dummyHead;
    Node current;

    dummyHead = new Node();
    current = dummyHead;

    while (a != null && b != null) {
        if ((int) a.getData() <= (int) b.getData()) {
            current.link = a;
            a.link = a;
        }
        else {
            current.link = b;
            b.link = a;
        }
        current = current.link;
    }
    current.link = (a == null) ? b : a;
    return dummyHead;
}

public Node getMiddle(Node head) {
    if (head == null) {
        return head;
    }
    Node slow, fast;
    slow = fast = head;
    while (fast.link != null && fast.link.link != null) {
        slow = slow.link;
        fast = fast.link.link;
    }
    return slow;
}

In the main method: 在主要方法中:

  Object data;
    MyLinkedList list = new MyLinkedList();         //empty list.


    for (int i = 0; i < 3; i++) {           //filling the list
        data = console.nextInt();
        list.insertAtFront(data);
    }


    System.out.print("Print(1): ");
    list.printList();

   list.mergeSort(list.getHead());
    System.out.print("List after sorting: ");
    list.printList();

One problem is the getMiddle method doesn't correctly return the middle Node . 一个问题是getMiddle方法不能正确返回中间Node

Consider a linked list with 5 Nodes (a, b, c, d, e) 考虑一个具有5个节点(a,b,c,d,e)的链表

head , slow , and fast all begin at index 0 (a). headslowfast都从索引0(a)开始。

After the first iteration of the while loop, slow is at 1 (b) and fast is at 2 (c); while循环的第一次迭代之后, slow为1(b), fast为2(c); after the second iteration, slow is at 2 (c) and fast at 4 (e). 在第二次迭代之后, slow为2(c),快速为4(e)。 These are both not null, so another iteration happens, putting slow at at 3 (d) and fast at null . 它们都不都是null,所以又发生了一次迭代,将慢速设为3(d),将快速null Since fast is null, the while loop is exited and slow is returned; 由于fast为null,因此退出while循环并返回slow ; however slow has node 3 (d) rather than the middle node, 2 (c). 但是slow是节点3(d),而不是中间节点2(c)。

An alternate way to get the middle node would be to simply use the number of nodes: 获取中间节点的另一种方法是仅使用节点数:

public Node getMiddle(Node head) {
    Node counter = head;
    int numNodes = 0;
    while(counter != null) {
        counter = counter.link;
        numNodes++;
    }
    if(numNodes == 0)
        return null;
    Node middle = head;
    for(int i=0; i<numNodes/2; i++)
        middle = middle.link;
    return middle;
}

I your mergeSort method is fine, but technically it only needs to return head if head.link is null , not if head itself is null (since that would never happen anyhow): 我的mergeSort方法很好,但是从技术上讲,如果head.linknull ,则只需要返回head ,而不是head本身为null (因为无论如何都不会发生):

public Node mergeSort(Node head) {
    if (head.link == null) {
        return head;       
    }
    // same
}

Most importantly, your merge method. 最重要的是,您的merge方法。 You can write a public void setData(Object) method in your Node class to make this easier. 您可以在Node类中编写一个public void setData(Object)方法,以使此操作更容易。 The following code should work, although I can't claim it's the best/most efficient way to do the job 以下代码应该可以工作,尽管我不能断言这是完成这项工作的最好/最有效的方法

public Node merge(Node a, Node b) {
    Node combined = new Node();
    Node current = combined;
    while(a != null || b != null) {
        if(a == null)
            addNode(current, b);
        if(b == null)
            addNode(current, a);
        if((int)a.getData()<(int)b.getData())
            addNode(current, a);
        else
            addNode(current, b);
    }
    return combined;
}

Uses the following helper method: 使用以下辅助方法:

public void addNode(Node n1, Node n2) {
    n1.setData((int)n2.getData());
    n1.link = new Node();
    n1 = n1.link;
    n2 = n2.link
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM