尝试对链表进行排序
Attempting to sort a linked list
我已经知道这个问题的各种答案。但是我的代码中有一个非常令人困惑的错误。下面是一系列的 println() 调用,看看我创建的列表是否正确排序。
ListNode list_b = new ListNode(3, new ListNode(-2));
System.out.println("Checking the string conversion: " +
sut.convertToString(list_b)); //output is 3,-2, as expected. Expected result of sorting is -2,3.
System.out.println("Now checking the
string conversion of the sorted list: " +
sut.convertToString(sut.sort(list_b, int_comparator))); //output is -2,3 as expected.
System.out.println("Now this is list_b following the sorting,
by calling the element and next directly: "
+ list_b.element + "," + list_b.next); //3,null. How the hell did that happen!?!??!!?
convertToString方法如下:
public String convertToString(ListNode head) {
if (head != null) {
String representation = "";
if (!head.element.equals(null))
representation += head.element.toString();
ListNode next = null;
if (head.next != null)
next = head.next;
if (next != null && !next.element.equals(null))
representation += "," + next.element.toString();
while (next != null) {
if (next.next != null) {
next = next.next;
if (!next.element.equals(null))
representation += "," + next.element.toString();
}
else
break;
}
return representation;
}
else
return "";
}
实际的排序方法仍在进行中,尽管相当简单:
public ListNode sort(ListNode head, Comparator comparator) {
if (head != null) {
ListNode next = null;
if (head.next != null)
next = head.next;
else
return head;
if (comparator.compare(head.element, next.element) > 0) {
head.next = next.next;
next.next = head;
head = next;
}
return head;
}
return null;
}
有人愿意解释一下我是如何做到这看似不可能的事情的吗?我无语怎么会这样!非常感谢任何可以解释的人!
编辑:感谢那些人的回答和建议。我应该澄清一下,然后在列表上执行以下测试:
assertTrue(sut.deepEquals(list_a, sut.sort(list_a, int_comparator)));
assertFalse(sut.deepEquals(list_b, sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-2, new ListNode(3)), sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-14, new ListNode(-2, new ListNode(3))), sut.sort(list_c, int_comparator)));
显然,这意味着 list_b 的任何更新(即 list_b = sut.sort(list_b))都是不必要的。我想问的是您将如何更改排序方法本身,以便不需要更新。
list_b
引用包含 3 的节点,并将节点 2 作为下一个元素。
然后你对列表进行排序。这改变了包含 3 的节点:它的下一个节点现在为空,因为它成为列表的最后一个元素。它还更改了节点 2,它现在将节点 3 作为下一个元素。但是 list_b 仍然是对包含 3.
的节点的引用
当您打印节点 list_b 时,您将得到 3, null
作为结果。
编辑:
回答你的最后一个问题:
how you would change the sort method itself so that updating is unnecessary
您应该有一个实际的 LinkedList class(与标准 java.util.LinkedList class 完全一样)。您拥有的 class 不代表列表。它代表节点链中的一个节点。
LinkedList class 将具有对头节点的引用,并将包含迭代存储在列表中的值、将其转换为字符串、对其进行排序等所需的所有方法。当然,对列表进行排序意味着更改对 LinkedList 对象内头节点的引用。但这对 LinkedList class 的用户来说是透明的,他们永远不会直接操作节点。
当然,如果您开始非常关心拥有一个合适的 LinkedList class,您应该简单地使用标准的,它是标准的、有文档记录的和经过测试的。
非常简单:您在这段代码中对列表进行排序:
sut.convertToString(sut.sort(list_b, int_comparator)))
列表是这样转换的:
3 -> -2 -> null ====> -2 -> 3 -> null
^ ^
| |
list_b list_b
sut.sort
returns 列表的新前面(头),应该是新的list_b
,但是由于你不更新值,它指向列表中的第二个节点,因此产生 "3 , null"
嗯...您正在更改 sort
方法中传递的节点的内部结构。变量 list_b
仍然引用排序后不再有后继节点的节点“3”。
您的排序方法正在返回排序列表的新头。但是你以后不要用它!
将您的代码片段更改为:
list_b = sut.sort(list_b, int_comparator);
System.out.println(sut.convertToString(list_b));
我已经知道这个问题的各种答案。但是我的代码中有一个非常令人困惑的错误。下面是一系列的 println() 调用,看看我创建的列表是否正确排序。
ListNode list_b = new ListNode(3, new ListNode(-2));
System.out.println("Checking the string conversion: " +
sut.convertToString(list_b)); //output is 3,-2, as expected. Expected result of sorting is -2,3.
System.out.println("Now checking the
string conversion of the sorted list: " +
sut.convertToString(sut.sort(list_b, int_comparator))); //output is -2,3 as expected.
System.out.println("Now this is list_b following the sorting,
by calling the element and next directly: "
+ list_b.element + "," + list_b.next); //3,null. How the hell did that happen!?!??!!?
convertToString方法如下:
public String convertToString(ListNode head) {
if (head != null) {
String representation = "";
if (!head.element.equals(null))
representation += head.element.toString();
ListNode next = null;
if (head.next != null)
next = head.next;
if (next != null && !next.element.equals(null))
representation += "," + next.element.toString();
while (next != null) {
if (next.next != null) {
next = next.next;
if (!next.element.equals(null))
representation += "," + next.element.toString();
}
else
break;
}
return representation;
}
else
return "";
}
实际的排序方法仍在进行中,尽管相当简单:
public ListNode sort(ListNode head, Comparator comparator) {
if (head != null) {
ListNode next = null;
if (head.next != null)
next = head.next;
else
return head;
if (comparator.compare(head.element, next.element) > 0) {
head.next = next.next;
next.next = head;
head = next;
}
return head;
}
return null;
}
有人愿意解释一下我是如何做到这看似不可能的事情的吗?我无语怎么会这样!非常感谢任何可以解释的人!
编辑:感谢那些人的回答和建议。我应该澄清一下,然后在列表上执行以下测试:
assertTrue(sut.deepEquals(list_a, sut.sort(list_a, int_comparator)));
assertFalse(sut.deepEquals(list_b, sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-2, new ListNode(3)), sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-14, new ListNode(-2, new ListNode(3))), sut.sort(list_c, int_comparator)));
显然,这意味着 list_b 的任何更新(即 list_b = sut.sort(list_b))都是不必要的。我想问的是您将如何更改排序方法本身,以便不需要更新。
list_b
引用包含 3 的节点,并将节点 2 作为下一个元素。
然后你对列表进行排序。这改变了包含 3 的节点:它的下一个节点现在为空,因为它成为列表的最后一个元素。它还更改了节点 2,它现在将节点 3 作为下一个元素。但是 list_b 仍然是对包含 3.
的节点的引用当您打印节点 list_b 时,您将得到 3, null
作为结果。
编辑:
回答你的最后一个问题:
how you would change the sort method itself so that updating is unnecessary
您应该有一个实际的 LinkedList class(与标准 java.util.LinkedList class 完全一样)。您拥有的 class 不代表列表。它代表节点链中的一个节点。
LinkedList class 将具有对头节点的引用,并将包含迭代存储在列表中的值、将其转换为字符串、对其进行排序等所需的所有方法。当然,对列表进行排序意味着更改对 LinkedList 对象内头节点的引用。但这对 LinkedList class 的用户来说是透明的,他们永远不会直接操作节点。
当然,如果您开始非常关心拥有一个合适的 LinkedList class,您应该简单地使用标准的,它是标准的、有文档记录的和经过测试的。
非常简单:您在这段代码中对列表进行排序:
sut.convertToString(sut.sort(list_b, int_comparator)))
列表是这样转换的:
3 -> -2 -> null ====> -2 -> 3 -> null
^ ^
| |
list_b list_b
sut.sort
returns 列表的新前面(头),应该是新的list_b
,但是由于你不更新值,它指向列表中的第二个节点,因此产生 "3 , null"
嗯...您正在更改 sort
方法中传递的节点的内部结构。变量 list_b
仍然引用排序后不再有后继节点的节点“3”。
您的排序方法正在返回排序列表的新头。但是你以后不要用它!
将您的代码片段更改为:
list_b = sut.sort(list_b, int_comparator);
System.out.println(sut.convertToString(list_b));