简体   繁体   中英

Remove items from the end of a linked list

I have the following implementation of a LinkedList.

package assignment10;
// A linked list is a sequence of nodes with efficient
// element insertion and removal.
// This class contains a subset of the methods of the
// standard java.util.LinkedList class.

import java.util.NoSuchElementException;

public class LinkedList {

    //nested class to represent a node
    private class Node {

        public Object data;
        public Node next;
    }

    //only instance variable that points to the first node.
    private Node first;

    // Constructs an empty linked list.
    public LinkedList() {
        first = null;
    }

    // Returns the first element in the linked list.
    public Object getFirst() {
        if (first == null) {
            NoSuchElementException ex
                    = new NoSuchElementException();
            throw ex;
        } else {
            return first.data;
        }
    }

    // Removes the first element in the linked list.
    public Object removeFirst() {
        if (first == null) {
            NoSuchElementException ex = new NoSuchElementException();
            throw ex;
        } else {
            Object element = first.data;
            first = first.next;  //change the reference since it's removed.
            return element;
        }
    }

    // Adds an element to the front of the linked list.
    public void addFirst(Object element) {
        //create a new node
        Node newNode = new Node();
        newNode.data = element;
        newNode.next = first;
        //change the first reference to the new node.
        first = newNode;
    }

    // Returns an iterator for iterating through this list.
    public ListIterator listIterator() {
        return new LinkedListIterator();
    }

    /**
     * *******************************************************
     * Add your methods here
     * *******************************************************
     */
    public String toString() {
        String string;
        if (size() == 0) {
            string = "{ }";
        } else {
            string = "{ ";
            StringBuilder sb = new StringBuilder();
            ListIterator iterator = listIterator();
            while (iterator.hasNext()) {
                sb.append(String.valueOf(iterator.next())).append(" ");
            }
            sb.append("}");
            string = string.concat(sb.toString());
        }

        return string;
    }

    public int size() {
//          int size=0;
//          while(this.listIterator().hasNext()){
//              this.listIterator().next();
//              size++;
//          }
//          return size;
        int size = 0;
        ListIterator iterator = listIterator();
        while (iterator.hasNext()) {
            iterator.next();
            size++;
        }

        return size;
    }

    public void addElementAt(Object element, int index) {
        ListIterator listIterator = this.listIterator();
        int size = size();
        if (size == 0) {
            this.listIterator().add(element);
        } else {
            int i= 0;
            while(i<index-1){
                listIterator.next();
            }
            listIterator.add(element);
//            Node _head = new Node();
//            Node node = new Node();
//            node.data = element;
//            int ix = index - 1;
//            node.next = _head;
//
//            Node previous = _head;
//
//            for (int i = size - 1; i > ix; --i) {
//                previous = previous.next;
//            }
//
//            Node position = previous.next;
//
//            previous.next = node;
//            node.next = position;
//            ++size;
        }
    }

    public void addFewAtEnd(Object element, int howMany) {
        ListIterator listIterator = this.listIterator();
        int i=0;
        while(i<howMany){
           listIterator.add(element);
        }
    }

    public void removeLastFew(int howMany) {
        ListIterator listIterator = this.listIterator();
        int size = size();
        int i=0;
        if(howMany>0){
            if(howMany<size){
                while(i<size){
                    listIterator.next();
                }
                for(int removed=0;removed<howMany;removed++){
                    listIterator.remove();
                    listIterator.next();
                }
            } else {
                while(i<size){
                    listIterator.next();
                }
                for(int removed=0;removed<size;removed++){
                    listIterator.remove();
                    listIterator.next();
                }
            }
        }
    }

    public void removeAllOccurrences(Object stringToBeRemoved) {
         ListIterator listIterator = this.listIterator();
         while(listIterator.hasNext()){
             if(String.valueOf(listIterator.next()).equalsIgnoreCase(stringToBeRemoved.toString())){
                 listIterator.next();
             } else {
                 listIterator.next();
             }

         }
    }

    public void reverseLastFew(int howMany) {
        ListIterator listIterator = this.listIterator();
        int size = size();
        int i=0;
        if(howMany>0){
            if(howMany<size){
                LinkedList linkedList = new LinkedList();
                while(this.listIterator().hasNext()){
                    listIterator.next();
                }
                int count=0;
                while(count<howMany){
                    linkedList.listIterator().add(listIterator.next());
                    listIterator().remove();
                    listIterator.next();
                }

            } else {
                LinkedList linkedList = new LinkedList();
                 int count=0;
                while(count<size){
                    linkedList.listIterator().add(listIterator.next());
                    listIterator().remove();
                    listIterator.next();
                }
                count = 0;
                while(linkedList.listIterator().hasNext()){
                    if(count==0){
                        this.addFirst(linkedList.first);
                    } else {
                        this.addElementAt(linkedList.listIterator().next(), count);
                    }
                }
            }
        }
    }

    //nested class to define its iterator
    private class LinkedListIterator implements ListIterator {

        private Node position; //current position
        private Node previous; //it is used for remove() method

        // Constructs an iterator that points to the front
        // of the linked list.
        public LinkedListIterator() {
            position = null;
            previous = null;
        }

        // Tests if there is an element after the iterator position.
        public boolean hasNext() {
            if (position == null) //not traversed yet
            {
                if (first != null) {
                    return true;
                } else {
                    return false;
                }
            } else {
                if (position.next != null) {
                    return true;
                } else {
                    return false;
                }
            }
        }

        // Moves the iterator past the next element, and returns
        // the traversed element's data.
        public Object next() {
            if (!hasNext()) {
                NoSuchElementException ex = new NoSuchElementException();
                throw ex;
            } else {
                previous = position; // Remember for remove

                if (position == null) {
                    position = first;
                } else {
                    position = position.next;
                }

                return position.data;
            }
        }

        // Adds an element before the iterator position
        // and moves the iterator past the inserted element.
        public void add(Object element) {
            if (position == null) //never traversed yet
            {
                addFirst(element);
                position = first;
            } else {
                //making a new node to add
                Node newNode = new Node();
                newNode.data = element;
                newNode.next = position.next;
                //change the link to insert the new node
                position.next = newNode;
                //move the position forward to the new node
                position = newNode;
            }
            //this means that we cannot call remove() right after add()
            previous = position;
        }

        // Removes the last traversed element. This method may
        // only be called after a call to the next() method.
        public void remove() {
            if (previous == position) //not after next() is called
            {
                IllegalStateException ex = new IllegalStateException();
                throw ex;
            } else {
                if (position == first) {
                    removeFirst();
                } else {
                    previous.next = position.next; //removing
                }
                //stepping back
                //this also means that remove() cannot be called twice in a row.
                position = previous;
            }
        }

        // Sets the last traversed element to a different value.
        public void set(Object element) {
            if (position == null) {
                NoSuchElementException ex = new NoSuchElementException();
                throw ex;
            } else {
                position.data = element;
            }
        }

    } //end of LinkedListIterator class
} //end of LinkedList class

And

package assignment10;
// The ListIterator interface allows access of a position in a linked list.
// This interface contains a subset of the methods of the
//  standard java.util.ListIterator interface. The methods for
//  backward traversal are not included.

public interface ListIterator
{
   //Move Moves the iterator past the next element.
   Object next();

   // Tests if there is an element after the iterator position.
   boolean hasNext();

   // Adds an element before the iterator position
   // and moves the iterator past the inserted element.
   void add(Object element);


   // Removes the last traversed element. This method may
   // only be called after a call to the next() method.
   void remove();

   // Sets the last traversed element to a different value.
   void set(Object element);
}

The method removeLastFew() is supposed to remove the specified number of items from the LinkedList at the end. How can I achieve this? At the moment, the method is not working.

You have a few options here.

Option 1:

This is the ugly and slow but easy.

Create a removeLast() and call it as many times as needed.

Of course, if you need this for a serious production, it will be too slow (but I doubt that, given the -non existent- complexity of the question). And if it is for an assignment and I were your professor you would most likely fail that one.

I guess you can do that by yourself.

Option 2:

This might be the most efficient, and it's not hard either (but it's not really elegant either).

For every element node on the list, just check if n th element (being n the number of elements you want to erase) since node is null. If that is the case, set to null the reference to node (you have to store the previous Node, yes).

If you need to do it with the "remove" function, just use a simple loop once you have found the element described above.

Option 3: (recursive).

This one is the one I like the most, but I have always been a big fan of recursion.

Create a function that goes all the way to the end, and then starts erasing.

Simple example (you will have to adapt it to your code, of course):

private int removeLast (int n, Node node) {
    int remaining = n;

    if (node.next != null) {
        remaining = removeLast (n, node.next);
    }

    if (remaining > 0) {
        remove(node);
        remaining--;
    }

    return remaining;
}

NOTE: I'm not sure if this would work, jsut made it from the top of my head, and didn't test it, just a pseudocode in case you want to do it this way (recommended Opt 2).

I see probably bug here:

while(i<size) {
    listIterator.next();
}

there is missing increment of i. And fix the condition something like this:

i < (size-howMany)

Also when deleting item, you must firstly save the value from "next".

a simple way

add a length property in your LinkedList then when you need to delete n nodes, go to the "length-n th" Node (some getNext()s in a while loop) and delete the rest!

don't forget to keep length valid

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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