java - 用链表实现归并排序
问题描述
我正在尝试在网上找到的一个问题,即使用链表实现合并排序,但是使用我学校教授的奇怪的列表接口实现而不是仅使用节点,因此从其他解决方案中简单复制在这里不起作用。我通常只是在扩展,BasicLinkedList
并没有真正打扰界面。这是我的驱动程序代码和类,合并排序并没有按照我想要的方式运行,调试了很长时间后我似乎无法弄清楚为什么。有谁可以帮我离开这里吗?
如果您需要更多信息,请通知我。
import java.util.*;
class Main {
public static void main(String [] args) {
BasicLinkedList<Integer> lst = BasicLinkedList.of(4,2,1,3);
BasicLinkedList<Integer> sortedList = BasicLinkedList.mergeSort(lst);
sortedList.print();
}
}
class ListNode <E> {
protected E element;
protected ListNode <E> next;
/* constructors */
public ListNode (E item) {
element = item;
next = null;
}
public ListNode (E item, ListNode <E> n) {
element = item;
next=n;
}
/* get the next ListNode */
public ListNode <E> getNext ( ) {
return this.next;
}
/* get the element of the ListNode */
public E getElement ( ) {
return this.element;
}
public void setNext(ListNode<E> item) {
this.next = item;
}
}
class BasicLinkedList <E> implements LinkedListInterface <E> {
protected ListNode <E> head = null;
protected int num_nodes = 0;
public boolean isEmpty()
{ return (num_nodes == 0); }
public int size( )
{ return num_nodes; }
public E getFirst ( ) throws NoSuchElementException {
if (head == null)
throw new NoSuchElementException("can't get from an empty list");
else return head.element;
}
public boolean contains (E item) {
for (ListNode <E> n = head; n!= null; n=n.next)
if (n.getElement().equals(item)) return true;
return false;
}
public void addFirst (E item) {
head = new ListNode <E> (item, head);
num_nodes ++;
}
public E removeFirst ( ) throws NoSuchElementException {
ListNode <E> ln;
if (head == null)
throw new NoSuchElementException ("can't remove from an empty list");
else {
ln = head;
head = head.next;
num_nodes --;
return ln.element;
}
}
public void print2 ( ) throws NoSuchElementException {
if (head == null)
throw new NoSuchElementException ("Nothing to print...");
ListNode <E> ln = head;
System.out.print ("List is: " + ln.element);
for (int i=1; i < num_nodes; i++) {
ln = ln.next;
System.out.print (", " + ln.element );
}
System.out.println(".");
}
public void print () throws NoSuchElementException {
if (head == null)
throw new NoSuchElementException ("Nothing to print...");
Iterator <E> itr = iterator();
System.out.print ("List is: " + itr.next() );
while (itr.hasNext())
System.out.print ( ", " + itr.next() );
System.out.println(".");
}
public Iterator<E> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<E> {
private ListNode<E> current = head;
public boolean hasNext(){ return current != null;}
public void remove() { throw new UnsupportedOperationException(); }
public E next() {
if ( !hasNext()) {
throw new NoSuchElementException();
}
E element = current.element;
current = current.next;
return element;
}
}
public static <E> BasicLinkedList<E> of(E ... values) {
BasicLinkedList<E> lst = new BasicLinkedList<>();
for (int i=values.length-1;i> -1; i--) {
lst.addFirst(values[i]);
}
return lst;
}
public static BasicLinkedList<Integer> mergeSort(BasicLinkedList<Integer> original) {
if (original.size() < 2) {
return original;
} else {
int totalSize = original.size();
int newSize = totalSize/2;
ListNode<Integer> middle = getMiddle(original);
ListNode<Integer> nextOfMiddle = middle.next;
BasicLinkedList<Integer> right = new BasicLinkedList<>();
right.head = nextOfMiddle;
right.num_nodes = totalSize- newSize;
//Create the left list, firstly by creating an empty shell and replace the head node
BasicLinkedList<Integer> left = new BasicLinkedList();
left.head = original.head;
right.num_nodes = newSize;
// set the next of middle node to null
middle.setNext(null);
// System.out.println("Before MS");
// debug(left,right);
BasicLinkedList<Integer> newLeft = mergeSort(left);
BasicLinkedList<Integer> newRight = mergeSort(right);
// System.out.println("After MS");
BasicLinkedList<Integer> lst = merge(newLeft,newRight);
//lst.print();
return lst;
}
}
public static ListNode<Integer> getMiddle(BasicLinkedList<Integer> original) {
if (original.head == null)
return null;
ListNode<Integer> slowPtr = original.head;
ListNode<Integer> fastPtr = slowPtr.next;
while (fastPtr != null) {
fastPtr = fastPtr.next;
if(fastPtr!=null) {
slowPtr = slowPtr.next;
fastPtr=fastPtr.next;
}
}
return slowPtr;
}
//Merges 2 non-empty lists together
public static BasicLinkedList<Integer> merge(
BasicLinkedList<Integer> firstList,
BasicLinkedList<Integer> secondList) {
ListNode<Integer> firstHead = firstList.head;
ListNode<Integer> secondHead = secondList.head;
BasicLinkedList<Integer> newList = new BasicLinkedList<Integer>();
// move smaller node into newList, and maintain its tail
//debugNode(firstHead,secondHead);
if (firstHead.getElement() <= secondHead.getElement()) {
newList.head = firstHead;
firstHead = firstHead.getNext();
} else {
newList.head = secondHead;
secondHead = secondHead.getNext();
}
ListNode<Integer> newTail = newList.head;
while (firstHead != null && secondHead != null) {
// System.out.println("Before loop ");
// debugNode(firstHead,secondHead);
if (firstHead.getElement() < secondHead.getElement()) {
newTail.setNext(firstHead);
firstHead = firstHead.getNext();
} else {
newTail.setNext(secondHead);
secondHead = secondHead.getNext();
}
newTail = newTail.getNext();
// System.out.println("After loop ");
// debugNode(firstHead,secondHead);
}
if (firstHead != null)
newTail.setNext(firstHead);
if (secondHead != null)
newTail.setNext(secondHead);
// perform cleanup
firstList.head = null;
secondList.head = null;
return newList;
}
public static void debug(BasicLinkedList<Integer> left, BasicLinkedList<Integer> right) {
System.out.print("Left");
left.print();
System.out.print("Right");
right.print();
}
public static void debugNode(ListNode<Integer> first, ListNode<Integer> second) {
System.out.print("Left");
System.out.println(first.getElement());
System.out.print("Right");
System.out.println(first.getElement());
}
}
import java.util.*;
public interface LinkedListInterface <E> {
public boolean isEmpty( );
public int size ( );
public E getFirst () throws NoSuchElementException;
public boolean contains (E item);
public void addFirst (E item);
public E removeFirst ( ) throws NoSuchElementException;
public void print ();
// ....etc....
// ....etc....
}
根据我的主驱动代码如图所示,具有正确的归并排序功能,List is: 1, 2 ,3, 4.
应该在以[4,2,1,3]
. 我当前的合并排序打印出 [1,3,2,4] 并且我的调试尝试显示在注释的代码行中。
解决方案
在 methodBasicLinkedList<Integer> mergeSort
中,您没有设置链表的大小left
,而是将链表的大小设置了right
两次。
这是您的代码:
right.head = nextOfMiddle;
right.num_nodes = totalSize - newSize;
//Create the left list, firstly by creating an empty shell and replace the head node
BasicLinkedList<Integer> left = new BasicLinkedList();
left.head = original.head;
//here is the mistake
//change it to - left.num_nodes = newSize;
right.num_nodes = newSize;
PS:我不知道你用的是哪个IDE,但我建议你下载IntelliJ Idea并使用它的调试功能。此外,您可能还有其他极端情况需要测试。
推荐阅读
- google-cloud-platform - Google Vision API 服务帐号权限
- java - Java 逻辑错误 - 未显示第十位小数
- python - TPUEstimator 不更新元权重
- rxjs - RxJS forkJoin 链接请求?
- python - 使用 API 提取 5 年的 Twitter 数据
- node.js - Azure 应用服务上 Angular 应用的服务器端渲染导致 SNAT 端口耗尽
- lua - GLua 的问题:“GetModel() 不是字符串库的一部分”
- c - 非全局使用的 getopt (C) 中的错误?
- kubernetes - 如何在 k8s 中为非服务帐户创建不记名令牌
- android - 使用 Retrofit2 和 Flow 同时进行多个 API 调用