拆分循环链表时出现问题

时间:2019-03-07 14:41:45

标签: java nodes circular-list

任务:给定一个具有偶数个元素且参考头指向第一个节点的圆形链表,编写方法splitHalf将圆形链表分为两个半圆形。即CLL(5,34,14,25)变为CLL(5,34)和CLL(14,25)。

我尝试用Java尝试,但是扩展了给我的实现。看来我的驱动程序代码没有给我我想要的结果。我当前splitHalf的实现可能看起来很尴尬,因为最初的问题只是编写一种对返回类型没有任何要求的算法,并且我尝试在线修改返回类型为void的算法,因此我的splitHalf只是完成拆分后即可打印。

我期待

List is: 1, 2, 1.
List is: 2, 1, 2.
List is: 3, 4, 3.
List is: 4, 3, 4.

但是我得到了

List is: 2, 2, 2.
List is: 1, 1, 1.
List is: 4, 4, 4.
List is: 3, 3, 3.

有人可以告诉我splitHalf中的CircularLinkedList怎么了吗?这是我的代码。

import java.util.*;

class Main {
    public static void main(String [] args) {
        CircularLinkedList<Integer> lst = CircularLinkedList.of(1,2,3,4);
        lst.splitHalf(lst.head);

    }
}


class CircularLinkedList <E> extends TailedLinkedList <E> {

    public void addFirst (E item) {
        super.addFirst ( item );
        tail.next = head;
    }

    public void addLast (E item ) {
        super.addLast ( item );
        tail.next = head;
    }

    public E removeAfter (ListNode <E> current) throws NoSuchElementException {
        E temp = super.removeAfter (current);
        // up till here no problem as long as it is not the following cases:
        // case 1. removing both head and tail (but not done correctly by parent)
        if ( num_nodes == 0 ) {  // can't test for head==null here
            head = tail = null;
            return temp;
        }
        // tail and head are not null now
        // case 2a. removing head (because current==null)
        if (current == null) {
            System.out.println("case 2a");
            tail.next = head;
            return temp;
        }
        // case 2b. removing head (because current==tail)
        if ( tail.next != head) {
            System.out.println("case 2b");
            head = tail.next;
            return temp;
        }
        // case 3. removing tail (and not head, because current.next==tail)
        if (current.next == head) {
            tail = current;
            return temp;
        }
        return temp;
    }

    public E removeFirst ( ) throws NoSuchElementException {
        return removeAfter ( null );
    }

    // the one in ExtendedLinkedList can't be used due to infinite loop
    public E remove (E item) throws NoSuchElementException {
        if (head == null) throw new NoSuchElementException("can't find item");

        ListNode <E> n = head;
        ListNode <E> prev = null;
        for (int i=0; i < num_nodes; i++, prev=n, n=n.next)  
            if (n.element.equals(item)) 
                return removeAfter (prev);

        throw new NoSuchElementException ("can't find item to remove");
    }

    // the one in BasicLinkedList can't be used as it would go into infinite loop
    public boolean contains (E item) throws NoSuchElementException {
        if ( head == null ) return false;
        ListNode <E> n = head;
        for (int i=0; i < num_nodes; i++) { 
            if (n.element.equals(item)) { return true; }
            n = n.next;
        }
        return false;
    }

    /*
    *Alternative method to printing instead of the infinite loop printing that is inherited
    */
    public void truncatedPrint () throws NoSuchElementException {
        if (head == null)
            throw new NoSuchElementException ("Nothing to print...");

        Iterator <E> itr = iterator();
        System.out.print ("List is: " + itr.next() );
        for (int i=0;i< this.size();i++) {//just print the head again to be sure that this is circular
            System.out.print ( ", " + itr.next() );
        }   
        System.out.println(".");
    }


    public static <E> CircularLinkedList<E> of(E ... values) {
        CircularLinkedList<E> lst = new CircularLinkedList<>();
        for (int i=values.length-1;i> -1; i--) {
            lst.addFirst(values[i]);
        }
        return lst;
    }


    void splitHalf(ListNode<Integer> head) { 
        ListNode<Integer> slow_ptr = head; 
        ListNode<Integer> fast_ptr = head.next;
        if (head == null) { 
            return; 
        } 

        //move the pointers to correct place
        while (fast_ptr.next != head 
                && fast_ptr.next.next != head) { 
            fast_ptr = fast_ptr.next.next; 
            slow_ptr = slow_ptr.next; 
        } 



        //the slow pointer is currently the previous node of tne head for 2nd half
        ListNode<Integer> head2 = slow_ptr.next;
        ListNode<Integer> head1 = head;


        slow_ptr.next = head1;
        fast_ptr.next = head2;

        ListNode.printFromNode(head1,3);
        ListNode.printFromNode(slow_ptr,3);
        ListNode.printFromNode(head2,3);
        ListNode.printFromNode(fast_ptr,3);


    } 




}


class TailedLinkedList <E>  extends ExtendedLinkedList <E> {

    protected ListNode <E> tail = null;

    public ListNode <E> getTail() {
      return tail;
    }

    public void addFirst (E item ) {
    super.addFirst ( item );
    if (num_nodes == 1) 
        tail = head;
    }

    public void addLast (E item) {
    if (head != null) {    
      tail.next = new ListNode <E> ( item );
      tail = tail.next;
      num_nodes++;
    } else {
      tail = new ListNode <E> ( item );
      head = tail;
      num_nodes++;
    }
    }


    public void addAfter (ListNode <E> current, E item) {
    super.addAfter (current, item);

    if (current != null) {
      if (current == tail)  // can "if (current.next.next == null)" work too ?
        tail = current.next;
    } else {
      if (tail == null) tail = head;
    }
    }



    // we need to look through all deletion methods....
    public E removeAfter (ListNode <E> current) throws NoSuchElementException {
      E temp = super.removeAfter(current);

      if (current != null) {  
            if (current.next == null) tail = current;
      } else  // removing head
            if (head == null) tail = null;  

      return temp;
    }

    public E removeFirst ( ) throws NoSuchElementException {
      return removeAfter( null );
    }

    // Okay to use remove from ExtendedLinkedList 
    // public E remove (E item) throws NoSuchElementException {
}



class ExtendedLinkedList <E> extends BasicLinkedList <E> {

    // not in API Class LinkedList
    public ListNode <E> getFirstPtr ()
        { return head; }

    // not in API Class LinkedList
    public void addAfter (ListNode <E> current, E item) {
        if (current != null) { 
            current.next = new ListNode <E> (item, current.next);
            num_nodes++;
        } else {
            head = new ListNode <E> (item, head);
            num_nodes++;
        }
    }

    // not in API Class LinkedList
    public E removeAfter (ListNode <E> current) throws NoSuchElementException {
        E temp;
        if (current != null) {
            if (current.next != null) {
                temp = current.next.element;
                current.next = current.next.next;
                num_nodes --;
                return temp;
            } else throw new NoSuchElementException("No next node to remove");
        } else { // if current is null, assume we want to remove head
            if (head != null) {
                temp = head.element;
                head = head.next; 
                num_nodes --;
                return temp;
            } else throw new NoSuchElementException("No next node to remove");
        }
    }

    public E remove (E item) throws NoSuchElementException {
        if (head == null) throw new NoSuchElementException ("can't find item to remove");

        // besides the following, can also use iterator in BasicLinkedList.java
        for (ListNode <E> n=head, prev=null; n != null; prev=n, n=n.next) 
            if (n.getElement().equals(item) ) 
                return removeAfter (prev);

        throw new NoSuchElementException ("can't find item to remove");
    }
}



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 in a class which looks like a method, 
    *I thought at most property allowed
    */
    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;
        }
    }

    /*make just for int for now
    *rmber static must upfront declare first
    */
    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;
    }
}




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



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

    /*
    *My own setter of the right neighbour of the current node,
    *Without the concept of leftware traversion in the factory method
    */
    public void setNext(ListNode<E> item) {
        this.next = item;
    }

    /*
    *Prints from a single node, without knowing the list entity
    *Might be null and null cache wont know of this method, so make it static better
    *Some cases to know more about
    *Locate the correct node first, then print the printable element, this is a checklist
    *I would prefer using their toString then using a getElement then put to print?
    *Added in extra count, anyway there isn't a printFromNode
    */
    public static <E> void printFromNode (ListNode<E> head, int count) throws NoSuchElementException {
        if (head == null) {
            throw new NoSuchElementException ("Nothing to print...");
        }

        ListNode<E> ptr = head;
        System.out.print ("List is: " + ptr.next.getElement());
        count--;
        while (count>0 && ptr.next!=null) {
            System.out.print ( ", " + ptr.next.getElement());
            count--;
        }
        System.out.println(".");
    }

}

0 个答案:

没有答案