简体   繁体   English

链表合并排序的实现

[英]Implementation of merge sort with linked lists

I am trying out a question found online, which is to implement merge sort with linked list, but using the strange list interface implementation taught by my school instead of using just the nodes, so plain copying from other solutions does not work here. 我正在尝试在网上找到一个问题,该问题是使用链接列表实现合并排序,但是使用我学校教授的奇怪列表接口实现而不是仅使用节点,因此从其他解决方案进行的普通复制在这里不起作用。 I was usually just expanding on BasicLinkedList and didn't really bother with the interface. 我通常只是在BasicLinkedList扩展,而BasicLinkedListBasicLinkedList该界面。 This is my driver code and classes, and the merge sort does not run the way I want it to run and I can't seem to figure out why after debugging for a long time. 这是我的驱动程序代码和类,并且合并排序的运行方式不符合我希望的运行方式,而且经过长时间的调试,我似乎无法弄清原因。 Can anyone help me out here? 有人可以帮我从这里出去吗?

Do inform me if you need more information. 如果您需要更多信息,请告诉我。

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....
}

According to my main driver code as shown, with the right merge sort function, List is: 1, 2 ,3, 4. should be printed out when starting with a list of [4,2,1,3] . 根据所示的主驱动程序代码,使用正确的合并排序功能,从[4,2,1,3]列表开始时List is: 1, 2 ,3, 4.应打印出List is: 1, 2 ,3, 4. [4,2,1,3] .。 My current merge sort prints out [1,3,2,4] and my debugging attempts are shown in the commented lines of code. 我当前的合并排序打印出[1,3,2,4],并且我的调试尝试显示在代码的注释行中。

In method BasicLinkedList<Integer> mergeSort , you are not setting the size of the left linked list, rather you are setting the size of the right linked list twice. 在方法BasicLinkedList<Integer> mergeSort ,您没有设置left链表的大小,而是设置了两次right链表的大小。

Here is your code: 这是您的代码:

            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: I don't know which IDE you are using, but I would suggest you to download IntelliJ Idea and use its debugging features. PS:我不知道您使用的是哪个IDE,但是我建议您下载IntelliJ Idea并使用其调试功能。 Also, you might have other corner cases to test for. 另外,您可能还需要测试其他极端情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM