双链表上的冒泡排序

Posted

技术标签:

【中文标题】双链表上的冒泡排序【英文标题】:Bubble sort on double linked list 【发布时间】:2013-02-24 03:25:41 【问题描述】:

花了几个小时试图让冒泡排序的实现在双链表上工作。我的代码似乎可以通过一次,但在没有完成排序的情况下过早完成。任何指导将不胜感激。

public void bubbleSort()

    Node cur = head.getNext();
    boolean done = false;

    while (!done)
    
        done = true;
        while(cur != tail)
        
            if (cur.getNext().getCount()>cur.getCount())
            
                swap(cur.getNext(),cur);
                done=false;
            
            cur = cur.getNext();
        
    
 

我使用的交换方法似乎破坏了节点的放置,直到它成为两个节点之间的循环。

private void swap(Node n1, Node n2)

    Node b1, b2, a1, a2;
    System.out.println("Swapping n1: " + n1 + " with n2: " + n2);
    b1 = n2.getPrev();
    if (b1 == n1) // handle adjacent nodes
        b1 = n2;
    a1 = n2.getNext();

    b2 = n1.getPrev();
    if (b2 == n2) // handle adjacent nodes
        b2 = n1;
    a2 = n1.getNext();

    // swap

    n1.setPrev(b1);
    n1.setNext(a1);

    n2.setPrev(b2);
    n2.setNext(a2);

    b1.setNext(n1);
    a1.setPrev(n1);

    b2.setNext(n2);
    a2.setPrev(n2);

谢谢

【问题讨论】:

为什么不写一个比较器javarevisited.blogspot.com/2011/06/… 在链表中,将一个元素与其直接后继元素交换是一种特殊情况。那个案例有过测试吗?对于外循环的每次迭代,您确实需要返回到列表的开头。 逐步运行代码以获得一个简单的列表,并观察它的行为。 【参考方案1】:

我在您的代码中看到的问题:

你应该从head开始,而不是从head.getNext()开始。 您应该在每次 while(!done) 迭代时重新启动 Node cur

通过这些更改,您的代码应该是

public void bubbleSort() 
    boolean done = false;
    while (!done) 
        Node cur = head;
        done = true;
        while(cur != tail) 
            if (cur.getNext().getCount()>cur.getCount()) 
                swap(cur.getNext(),cur);
                done=false;
            
            cur = cur.getNext();
        
    

此代码假定您的 swap 方法可以正常工作。使用 int count 作为 Node 类中的数据进行测试,在列表中分配 10000 个 int 值。


编辑:根据您的问题编辑,我将Node 类和swap 函数设为:

private static class Node 
    int count;
    Node next;
    //getters and setters...


//this function just swaps data, no need to swap the nodes prev and next
//(note that yours is an algorithm design issue)
private void swap(Node node1, Node node2) 
    int aux = node1.getCount();
    node1.setCount(node2.getCount());
    node2.setCount(aux);

无需执行您在 swap 实现中完成的所有样板代码。

【讨论】:

然后我得到一个空指针错误,因为头部和尾部是哨兵标记。我很确定这是交换方法。 @efnx 我猜你的 LinkedList 实现有问题 =\。我做了一个快速测试,并像一个魅力一样工作。 @efnx 根据您的问题编辑,您为什么拥有所有样板代码?您只需要交换节点中的数据【参考方案2】:

在外循环的开头添加cur = head.getNext(); 对我的链表实现很有效。所以问题出在swap 方法或者你的列表的实现上。

根据您的bubbleSort 方法,swap 方法只交换节点的数据,而不是节点本身。我的意思是,它只是交换count 的值。如果不是这样,swap 方法就是问题所在。否则,你的双链表实现会有问题。

【讨论】:

感谢您的帮助。这绝对是交换方法。现在我只需要弄清楚出了什么问题。对于一个简单的 n 【参考方案3】:

您绝对需要将cur = head.getNext(); 保留在外部while 循环的末尾,否则在第二次通过时内部while 循环将被完全跳过并且完成将是真的。

您是否考虑过冒泡排序的运行时间?我在您对 MD.Unicorn 的回答中注意到,它适用于

对 100 个列表进行排序需要多长时间?

【讨论】:

在我的计算机中,100 个元素需要 4390 毫秒到 5038 毫秒,1000 个元素需要 12740 毫秒到 13608 毫秒。

以上是关于双链表上的冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章

冒泡排序双链表

Java中双链表的冒泡排序[重复]

我眼中的数组和冒泡排序

冒泡排序,算法以及优化

linux上的C-RPC(冒泡排序)

使用JavaScript完成排序算法:冒泡排序选择排序 快速排序