私は現在、単独リンクリストのためのマージメカニズムを策定しようとしています。これらは、このような操作を行うための重要な要素であることを研究し、マージソート単独リンクリストをソートするための最良の方法である)Aについて一貫性のあるアイデアを見つけ、そしてB)を通じ、私はこの次のコードで到着しました。それはほとんど意図どおりに動作しますが、最後の入力された数よりも大きい整数のすべてを返します。例えば、7、6、5、4、3、2入力、1、1、2、3、4、5、6、7、しかし1の入力、2、3、4、5のみ5. Iを戻します戻ります「それはちょうど逆の順序で番号を入力するには、ローカライズの問題ではないですので、使用されるランダム入力注文VEのが、文字通り任意の順序。数は、最終的な数よりも小さい場合は、ソート処理のリストから削除されます。私はすべてではこの原因を見つけることができません。
任意およびすべてのアドバイスや提案は、より多くの歓迎されている、とあなたが持っている任意の入力に感謝。私は本当にここにすべての入力/建設的な批判を歓迎するように、リンクされたリストと再帰の私の知識は、最大ではありません。
public Node mergeSort(Node head) {
if (head == null || head.getNext() == null) return head;
Node midpoint = findMidpoint(head);
Node rightliststart = midpoint.getNext();
midpoint.setNext(null);
Node rightlist = mergeSort(rightliststart);
Node sorted = sort(leftlist, rightlist);
return sorted;
}
public Node findMidpoint(Node head) {
if (head == null) return head;
Node slowpointer = head;
Node fastpointer = slowpointer.getNext();
while (fastpointer != null) {
fastpointer = fastpointer.getNext();
if (fastpointer != null) {
slowpointer = slowpointer.getNext();
fastpointer = fastpointer.getNext();
}
}
return slowpointer;
}
public Node sort(Node one, Node two) {
Node temp = null;
if (one == null) return two;
if (two == null) return one;
if (one.getData() <= two.getData()) {
temp = one;
temp.setNext(sort(one.getNext(), two));
}
else {
temp = two;
temp.setNext(sort(one, two.getNext()));
}
return temp;
}
例のマージコード。ダミー・ノードは、コードを簡略化するために使用されるどのようにこの番組は、(最初のノードがマージに更新ヘッドに特殊なケースを回避します)。
// merge two already sorted lists
static Node merge(Node list0, Node list1) {
if(list0 == null)
return list1;
if(list1 == null)
return list0;
Node temp = new Node(); // dummy node
Node dest = temp;
while(true){
if(list0.data <= list1.data){
dest.next = list0;
dest = list0;
list0 = list0.next;
if(list0 == null){
dest.next = list1;
break;
}
} else {
dest.next = list1;
dest = list1;
list1 = list1.next;
if(list1 == null){
dest.next = list0;
break;
}
}
}
return temp.next;
}
マージソートのコードダウンの例トップ。それはリストにのみ各再帰分割のN / 2個のノードを走査し、(高速、低速の)二重スキャンを避けるために、リストの大きさを得るために一回走査します。
// return size of list
static int size(Node head) {
int i = 0;
while(head != null){
head = head.next;
i++;
}
return i;
}
// advance to node n
static Node advance(Node head, int n) {
while(0 < n--)
head = head.next;
return head;
}
// top down merge sort for single link list entry function
static Node sorttd(Node head) {
int n = size(head);
if(n < 2)
return head;
head = sorttdr(head, n);
return head;
}
// top down merge sort for single link list recursive function
static Node sorttdr(Node head, int n) {
if(n < 2)
return head;
int n2 = (n/2);
Node node = advance(head, n2-1);
Node next = node.next;
node.next = null;
head = sorttdr(head, n2);
next = sorttdr(next, n-n2);
head = merge(head, next);
return head;
}
マージソートのコード例アップ底。これは、配列[i]は2 ^ Iノードとのリストであるリストの小(32)アレイを使用します。ノードが配列にマージされ、その配列は、単一のソートされたリストにマージされます。キャッシュに収まらない大きなリストでは、ランダムに散在のノードと、各ノードごとにキャッシュミスがたくさんあるだろうとは、マージソートアップケースの底が約30%速く、トップダウンよりも、アクセスします。
// bottom up merge sort for single link list
static Node sortbu(Node head) {
final int NUMLIST = 32;
Node[] alist = new Node[NUMLIST];
Node node;
Node next;
int i;
// if < 2 nodes, return
if(head == null || head.next == null)
return null;
node = head;
// merge node into array
while(node != null){
next = node.next;
node.next = null;
for(i = 0; (i < NUMLIST) && (alist[i] != null); i++){
node = merge(alist[i], node);
alist[i] = null;
}
if(i == NUMLIST) // don't go past end of array
i--;
alist[i] = node;
node = next;
}
// node == null
// merge array into single list
for(i = 0; i < NUMLIST; i++)
node = merge(alist[i], node);
return node;
}