Java 用冒泡排序实现双链表

Java 用冒泡排序实现双链表,java,linked-list,bubble-sort,Java,Linked List,Bubble Sort,我正在使用以下命令实现一个Dobly链表:import java.util.LinkedList为赋值使用气泡排序。通过对排序和链表的研究,我了解到我不应该使用索引对链表进行冒泡排序,因为链表中不存在索引,或者成功实现起来太麻烦 因此,在阅读了这些之后,我编写了以下代码,但我仍然不确定我是否走上了正确的道路 我需要一些帮助来理解使用dobly链表实现冒泡排序背后的逻辑 此外,我还需要一些保证,以确定我是否有效地走在正确的道路上,或者我在这个编码练习中的尝试是否完全错误 //This for l

我正在使用以下命令实现一个Dobly链表:import java.util.LinkedList为赋值使用气泡排序。通过对排序和链表的研究,我了解到我不应该使用索引对链表进行冒泡排序,因为链表中不存在索引,或者成功实现起来太麻烦

因此,在阅读了这些之后,我编写了以下代码,但我仍然不确定我是否走上了正确的道路

我需要一些帮助来理解使用dobly链表实现冒泡排序背后的逻辑

此外,我还需要一些保证,以确定我是否有效地走在正确的道路上,或者我在这个编码练习中的尝试是否完全错误

 //This for loop sorts the smaller part of the bubble sort.
for(int i = 0; i < cars.size() - 1; i++)
    {        //This part creates the second "larger" part of the bubble sort.
        for(int j = i + 1; j < cars.size(); j++)
        {


//Did I do this part correctly?  This is where the swap and sort of the bubble sort        takes //place.
//Obviously, I am using the comparable interface, since I am using the compareTo method.
//

//with the bubblesort, all elements must be greater than zero because for the bubble          //sort, 0 is the smallest element in a set of integers.


            if(cars.get(i).getName().compareTo(cars.get(j).getName()) > 0)
            {
                CarName cari = cars.get(i);
                CarName CarNamej = cars.get(j);
                cars.remove(i);
                cars.add(i, carj);
                cars.remove(j);
                cars.add(j, cari);
                }
            }
        }
    }

我是对的,还是我在所有代码中都做了一些完全错误的事情?

看起来你走的路不对。您需要完全消除索引的使用,而是使用节点引用。首先开发代码,从列表中删除一个元素,只给出对该元素的引用。然后开发代码,将一个元素插入到列表中,就在列表中已经存在的元素之前,只给出对这两个元素的引用。然后可以在这两种方法的基础上构建排序算法

例如,以下是删除元素的方法:

void remove(Element element) {
    element.previous().setNext(element.next());
    element.next().setPrevious(element.previous());
}

你应该理解双链接列表是如何工作的,来理解为什么这个代码应该在列表中间的元素中工作。根据列表的表示方式,可能需要测试结束条件(

element.previous()
和/或
element.next()
null
)。

考虑气泡排序在常规数组上的工作方式。简单的气泡排序实现如下所示:

   for (int i = array.Length; i > 0; i--)
        {
            for (int j = 0; j < i-1; j++)
            {
                if (array[j] > array[j+1])
                {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1]=tmp;
                }
                DisplayElements(array);
            }
        }    
for(int i=array.Length;i>0;i--)
{
对于(int j=0;j数组[j+1])
{
int tmp=数组[j];
数组[j]=数组[j+1];
阵列[j+1]=tmp;
}
显示元素(数组);
}
}    

不同之处在于,您必须将对列表中下一个和上一个节点的引用存储在数组或向量中,而不是使用临时int,您可以通过索引访问存储的变量,即项目列表中的位置

在链表中,您可以通过从一个项目跳到下一个项目来访问特定项目

由于您在代码中使用的是
get(i)
,因此在按列表中的位置进行索引时,显然使用的是数组或向量。所以,不。。。不幸的是,你完全走错了方向

一旦您越来越接近,您的代码将更像:

boolean changed = true;
while (changed) {  // keep going until we didn't make any more changes (not
                   // strictly the best condition for bubble sort, but it'll do)

    a = first;                  // grab first element
    b = a.next;                 // grab next element
    changed = false;
    while (b!=last) {           // run through all elements
        if (a.value>b.value) {  // compare the two elements; swap if out of order
            a.prev.next = b;    // update element before a to be followed by b
            b.next.prev = a;    // update element after b to be preceeded by a
            a.prev = b;         // b is now before a
            b.next = a;         // and a is after b
            changed = true;     // we made a change, so we're not done
        } else {
            a = b;              // if we didn't swap them, move to next pair
        }
        b = a.next;             // second half of next pair is next after a
    }
}
这只是给你一个粗略的想法。它绝不是完整的或没有bug的。例如,如果您在列表的最开始处,则需要首先更新
a.prev
,而不是
a.prev.next=b行中的
a.prev
,等等。。。但是嘿。。。反正你也不想让别人帮你做作业,对吧?;)

基本上,在双链接列表中,每个元素都知道如何到达下一个元素(a.next)和上一个元素(a.prev)。气泡排序是对这种链表进行排序的一种很好的选择,因为它只比较相邻的元素。否则,快速排序或合并排序或两者的组合可能会快得多,但它们确实需要对元素进行索引访问,而链表通常不提供这种访问

希望这有帮助

顺便说一句:Youtube上有一大堆很酷的视频,很好地解释了这些事情

还有一个更严重的问题:


还有一个更不寻常的例子:(其中一个用于快速排序的有更好的音乐:)

为什么不将链表转换成数组,对数组进行排序,然后将内容复制回链表中。

我认为你应该先用一种方法完成这个问题,然后询问是否有问题这就是问题所在,我正在以整数格式对一组数据进行排序,所以如果我使用bubbleSort的编码方式不是更好吗?根据我从参考资料中了解到的情况,LinkedList允许您不必关心要排序的信息的索引。因此,您只能关注信息本身。如果不使用数组进行冒泡排序,交换节点不是效率低下吗?@edxyz-也许我误解了。我的印象是您正在实现自己的双链接列表结构。如果您使用的是
java.util.LinkedList
,那么您当前的方法是好的。但是,我建议使用
set
而不是
remove
,然后使用
add
。是的。我正在使用import java.util.LinkedList;但我只需要澄清一下我的编码所涉及的逻辑,以确保我在正确的轨道上。在上面的代码中,我对逻辑的各个部分添加了更多的注释和解释。谢谢你。@edxyz-看起来基本上是对的。您似乎有一个输入错误,将变量命名为
caramej
,而不是
carj
。另外,正如我所说,我建议使用
cars.set(I,carj)而不是
车辆。删除(i)后接
cars.add(i,carj),位置
j
。是的,我知道使用数组进行冒泡排序是什么样子。谢谢你给我提神。我会记住这一点,并进一步理解我的代码。唯一要记住的是您使用的数据结构的差异。数组是按顺序排列的,而链表是按结构中的引用排列的。感谢视频。Java API内置了将列表转换为数组的方法,反之亦然。
boolean changed = true;
while (changed) {  // keep going until we didn't make any more changes (not
                   // strictly the best condition for bubble sort, but it'll do)

    a = first;                  // grab first element
    b = a.next;                 // grab next element
    changed = false;
    while (b!=last) {           // run through all elements
        if (a.value>b.value) {  // compare the two elements; swap if out of order
            a.prev.next = b;    // update element before a to be followed by b
            b.next.prev = a;    // update element after b to be preceeded by a
            a.prev = b;         // b is now before a
            b.next = a;         // and a is after b
            changed = true;     // we made a change, so we're not done
        } else {
            a = b;              // if we didn't swap them, move to next pair
        }
        b = a.next;             // second half of next pair is next after a
    }
}