在不重新链接节点的情况下对链表进行排序



我已经知道如何对链表进行排序,但我的方法与大多数同学有点不同。我没有重新链接节点,而是使用类似于mutator或setter方法的方法来对元素进行排序,并将元素放置在其适当的位置上

这里有一个例子:

for(Node<E> x = head.next; x != null; x = x.next) {
E temp = x.element;
Node<E> y = x.previous;
Node<E> p = y.next;
for(; y != null && y.element.compareTo(temp) > 0; y = y.previous) {
p = y;
y.next.setElement(y.element);                
}
p.setElement(temp);
}

这是正确的。

现在我的问题是,如果我做这样的事情而不是复杂的节点重新链接,我会作弊吗?这对排序链表来说是一种糟糕的做法吗?

排序算法:[emphasis added]

在计算机科学中,排序算法是将列表的元素按特定顺序排列的算法。

链表的元素是一个节点,它由数据和列表中下一个节点的引用(链接(组成。

在对链表进行排序的方式中,您只是将链表元素的数据部分移动/放置到其适当位置,但引用部分仍然是指代相同的下一个节点。排序后打印列表时,您将按排序顺序获得输出,但实际上您只移动了列表的数据部分,而不是整个元素,我认为这不是排序链表的合适方式。

考虑一个例子:
一个双链表,其中ele是类的成员,它保存int类型的数据,previousnext是保存上一个和下一个节点引用的成员。Node类将是这样的:

class Node{  
int ele;  
Node previous;
Node next;
....
....
}  

现在您已经编写了在排序时将元素ele值放置在适当位置的代码。

假设您需要向链接列表的节点添加更多信息:

class Node{
int element;
char char_ele;    // newly added member
string str_ele;   // newly added member
Node previous;
Node next;
....
....
}

现在有了这个更改,您必须对排序代码进行更改,以便在排序时将char_elestr_eleele一起放置在适当的位置。但是,如果您实现了一个正确的链表排序,其中节点根据排序条件重新链接,那么无论节点的数据部分发生了什么变化,都不需要对您的实现进行任何更改。

您的方法没有任何欺骗行为。这完全取决于你需要什么。如果您不需要交换引用,那么您实现的方法会更简单,不应该有任何其他问题。

但是假设您的节点是一个更复杂的对象。从可读性的角度来看,复制内容可能不太好。或者,您的用例需要交换引用,那么在需要交换引用时,为了可读性和唯一选项,最好重新排列节点。

事实上,这是面试问题"在不更改任何下一个字段的情况下对链表进行排序"的解决方案。然而,是一种作弊,使用最简单的方法,因为它没有显示出任何处理指针的能力。使用指针,您可以更改标题或下一个字段。只要节点不向公众公开(这无论如何都是个坏主意(,您的版本就可以工作。

现在,你可以通过获得指针的经验(因为这仍然很容易(,让你未来的编程工作变得更加容易。

信息:

你在0中为我行走。。N、 对于i+1中的j。。其复杂度为O(N²(-二次型。元素的3倍,慢9倍。

对于阵列,可以得到O(N log N(,这要快得多。

我不认为这是一种糟糕的做法。这甚至是Java自己的List.sort所做的,只是它更进一步,在数组中对列表之外的元素进行排序:

获取一个包含此列表中所有元素的数组,对数组进行排序,并在此列表上迭代,从数组中的相应位置重置每个元素

Code(来自OpenJDK,未在线找到Oracle的(:

default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}

最新更新