所以,任務是實現鏈接列表和合並排序鏈接列表。我完全意識到,在行業中,我很可能不必實現其中的任何一種,但我認爲這是練習Java的好方法。以下是我已經得到了這一點:以Java的方式合併排列LinkedList
Node類:
public class Node<E extends Comparable<E>>
{
public E data;
public Node<E> next;
public Node(E data)
{
this.data = data;
next = null;
}
public void printData()
{
System.out.print(data + " ");
}
}
LinkedList類:
public class LinkedList<E extends Comparable<E>>
{
protected Node<E> root;
protected int size = 0;
public LinkedList()
{
root = null;
}
public void addBeg(E e)
{
Node<E> newNode = new Node<E>(e);
newNode.next = root;
root = newNode;
size++;
}
public Node deleteBeg()
{
Node<E> temp = root;
if(!isEmpty())
{
root = root.next;
size--;
}
return temp;
}
public void setRoot(Node<E> newRoot)
{
root = newRoot;
}
public boolean isEmpty()
{
return root == null;
}
public Node<E> getRoot()
{
return root;
}
public void printList()
{
Node<E> cur = root;
while(cur!=null)
{
cur.printData();
cur=cur.next;
}
System.out.println();
}
}
MergeSorter類:
public class MergeSorter<E extends Comparable<E>>
{
public MergeSorter()
{
}
private void split(LinkedList<E> list, LinkedList<E> firHalf, LinkedList<E> secHalf)
{
//if 0 or only 1 elements in the list - it doesn't seem to work, however
if(list.getRoot() == null || list.getRoot().next == null)firHalf = list;
else{
Node<E> slow = list.getRoot();
Node<E> fast = list.getRoot().next;
while(fast!=null)
{
fast = fast.next;
if(fast!=null)
{
fast = fast.next;
slow = slow.next;
}
}
//If I use the following line firHalf list is empty when in the caller of this method (it's not in this method, however). Don't understand why):
//firHalf = list;
firHalf.setRoot(list.getRoot());
secHalf.setRoot(slow.next);
slow.next = null;
}
}
private LinkedList<E> merge(LinkedList<E> a, LinkedList<E> b)
{
LinkedList<E> mergedList = new LinkedList<E>();
Node<E> dummy = new Node<E>(null);
Node<E> tail = dummy;
while(true)
{
if(a.getRoot() == null){
tail.next = b.getRoot();
break;
}
else if(b.getRoot() == null){
tail.next = a.getRoot();
break;
}
else
{
if(a.getRoot().data.compareTo(b.getRoot().data) <= 0)
{
tail.next = a.getRoot();
tail = tail.next;
a.setRoot(a.getRoot().next);
}
else
{
tail.next = b.getRoot();
tail = tail.next;
b.setRoot(b.getRoot().next);
}
tail.next = null;
}
}
mergedList.setRoot(dummy.next);
return mergedList;
}
public void mergeSort(LinkedList<E> list)
{
Node<E> root = list.getRoot();
LinkedList<E> left = new LinkedList<E>();
LinkedList<E> right = new LinkedList<E>();
if(root == null || root.next == null) return; //base case
split(list, left, right); //split
mergeSort(left);
mergeSort(right);
list = merge(left, right); // when this mergeSort returns this list should be
// referenced by the left or right variable of the
// current mergeSort call (but it isn't!)
}
}
我對Java相當陌生(來自C背景),所以如果我的代碼完全錯誤,我真的很抱歉。當我獨立地測試MergeSorter類中的拆分和合並方法時,一切似乎都奏效(拆分由0或1個元素組成的列表不起作用,並且使我瘋狂,但這不是合併排序所需的)。然而,mergeSort方法不起作用,我似乎無法找到方法。我試圖自己調試它,當兩個半部分合併到一個列表中,然後遞歸返回時,似乎會出現問題。新的合併列表應該被當前mergeSort調用的左或右變量引用,但是我只能得到最後一個元素而不是整個列表。
啊,我明白你的觀點。非常感謝!但是,在我看來,這對於這麼簡單的任務來說代碼太多了。不會這樣: firHalf.setRoot(list.getRoot()); 做同樣的工作?我想通過值傳遞也是爲什麼合併在我的mergeSort方法不能正常工作時,遞歸返回? (: – user3192253
所以在我的mergeSort方法中,我添加了一個新的LinkedList mergedList來存儲左右合併列表:mergedList = merge(left,right),然後我將列表的根設置爲與這個mergedList由list.setRoot(mergedList.getRoot())和它的工作!但是,我覺得我的解決方案非常複雜(例如,與它看起來用C編寫的內容相比)。我的代碼中有哪些可以改進的地方?再次感謝! (: –
user3192253
@ user3192253:'firHalf.setRoot(list.getRoot())'會設置'firHalf'和'list'具有相同的實際根節點,而不僅僅是相同的根值,這意味着如果有人寫'list.getRoot()。value = ...'或'list.getRoot()。next = ...',這將改變這兩個列表。所以......是的,你應該這樣做,但只有*後*你改變你的'Node'類是不可變的,這樣它就可以在多個列表之間安全地共享(即:'Node.value'和'Node.next'都應該聲明爲'final'並且在構造函數中初始化。 ) – ruakh