首页 > 代码库 > 算法(Algorithms)第4版 练习 链表类 1.3.19~1.3.29

算法(Algorithms)第4版 练习 链表类 1.3.19~1.3.29

package com.qiusongde.linkedlist;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class LinkedList<Item> implements Iterable<Item> {
    
    private Node<Item> first;
    
    //Node should be public static in this class
    //When it comes to LinkedList, Node should be accessed outside
    public static class Node<E> {
        public E item;
        public Node<E> next;
    }
    /**
     * initialize LinkedList
     */
    public LinkedList() {
        first = null;
    }
    
    public LinkedList(Node<Item> first) {
        this.first = first;
    }
    
    /**
     * insert item at the beginning of the list
     * @param item the item to be inserted
     */
    public void insertAtBeginning(Item item) {
        
        Node<Item> oldfirst = first;
        
        first = new Node<Item>();
        first.item = item;
        first.next = oldfirst;
        
    }
    
    /**
     * remove the item at the beginning of the list
     * @return return the item at the beginning of the list
     * @throws NoSuchElementException if this Linked List is empty
     */
    public Item removeFromBeginning() {
        
        if(isEmpty()) 
            throw new NoSuchElementException("LinkedList is empty");
        
        Item item = first.item;
        first = first.next;
        
        return item;
    }
    
    //1.3.19
    /**
     * remove the last node in the linked list whose first node is first
     * 
     * @return return the item of the last node
     * @throws NoSuchElementException if this Linked List is empty
     */
    public Item removeTheLast() {
        
        Node<Item> precurrent;
        Item item = null;
        
        precurrent = findPreLastNode();
        
        //has not found
        if(precurrent.next == null) {
            throw new NoSuchElementException("LinkedList is empty");
        }
        
        item = precurrent.next.item;
        //some implementation will add one empty node as head, and head.next = first
        //if so, it‘s not necessary to have if condition here
        if(precurrent.next == first)
            first = first.next;
        else
            precurrent.next = precurrent.next.next;
        
        return item;    
    }
    
    /**
     * return the previous last node
     * 
     * @return return the previous last node. 
     * If the last node is the first node, the previous last node is a virtual one
     */
    private Node<Item> findPreLastNode() {
        
        Node<Item> precurrent = new Node<Item>();
        precurrent.next = first;
        
        //find the previous last node
        //precurrent.next is the same as current
        while(precurrent.next != null && precurrent.next.next != null) {
            precurrent = precurrent.next;
        }
        
        return precurrent;
    }
    
    //1.3.20
    /**
     * delete the kth element in a linked list, if it exists. 
     * 
     * @param k the kth element, it should larger than 1
     * @throws IllegalArgumentException if k < 1
     * @throws NoSuchElementException if the size of the list is less than k
     */
    public Item delete(int k) {
        
        if(k < 1)
            throw new IllegalArgumentException("k must larger than 1");
        
        Node<Item> precurrent = new Node<Item>();
        precurrent.next = first;
        Item item;
        
        while(precurrent.next != null && k > 1) {
            precurrent = precurrent.next;
            k--;
        }
        
        if(precurrent.next == null) 
            throw new NoSuchElementException("LinkedList hasn‘t so many elements");
        
        item = precurrent.next.item;
        if(precurrent.next == first)
            first = precurrent.next.next;
        else
            precurrent.next = precurrent.next.next;
        
        return item;
    }
    
    //1.3.21
    /**
     * find if some node in the list has key as its item field
     * 
     * @param list the linked list of T
     * @param key the T key
     * 
     * @return {@code true} some node exists. 
     *          {@code false} no node exist
     */
    public static <T> boolean find(LinkedList<T> list, T key) {
        
        for(T s : list) {
            if(s.equals(key))
                return true;
        }
        
        return false;
    }
    
    //1.3.24
    /**
     * remove the node following the node x
     * (and does nothing if the argument or the next field in the argument node is null)
     * 
     * @param x the given node
     */
    public static <T> void removeAfter(Node<T> x) {
        
        if(x == null || x.next == null) 
            return;
        
        Node<T> current = x.next;
        x.next = null;
        
        while(current != null) {
            Node<T> temp = current.next;
            current.next = null;
            current = temp;
        }
        
    }
    
    //1.3.25
    /**
     * insert the second node after the first on its list. 
     * and does nothing if either argument is null.
     * 
     * @param first the first node
     * @param second the second node to be inserted after the first
     */
    public static <T> void insertAfter(Node<T> first, Node<T> second) {
        
        if(first == null || second == null) 
            return;
        
        second.next = first.next;
        first.next = second;
        
    }
    
    //1.3.26
    /**
     * remove all of the nodes in the list that have key as its item field
     * 
     * @param list the linked list of T
     * @param key the T key
     * 
     * @return void
     * 
     */
    public static <T> void remove(LinkedList<T> list, T key) {
        Node<T> precurrent;
        precurrent = findPreNode(list, key);
        
        //remove all of the nodes
        while(precurrent.next != null) {
            
            if(precurrent.next == list.first)
                list.first = list.first.next;
            else
                precurrent.next = precurrent.next.next;
            
            precurrent = findPreNode(list, key);
        }
        
    }
    
    //1.3.26
    /**
     * find the node in the list whose item equals key
     * 
     * @param key the T key
     * 
     * @return return the previous node whose item equals key
     */
    private static <T> Node<T> findPreNode(LinkedList<T> list, T key) {
        Node<T> precurrent = new Node<T>();
        precurrent.next = list.first;
        
        while(precurrent.next != null && !precurrent.next.item.equals(key)) {
            precurrent = precurrent.next;
        }
        
        return precurrent;
    }
    
    
    //1.3.27
    /**
     * return the value of the maximum key in the list
     * 
     * @param list the linked list of Integer
     * 
     * @return return the maximum key in the list
     */
    public static int max(LinkedList<Integer> list) {
        
        if(list.first == null)
            return 0;
        
        int max = 0;
        for(int val : list) {
            if(val > max)
                max = val;
        }
        
        return max;
    }
    
    //1.3.28
    /**
     * return the value of the maximum key in the list by recursion
     * 
     * @param list the linked list of Integer
     * 
     * @return return the maximum key in the list
     */
    public static int maxByRecursion(LinkedList<Integer> list) {
        
        if(list.first == null)
            return 0;
        
        int first = list.first.item;//first item
        list.first = list.first.next;//remove first item in the list
        int max = maxByRecursion(list);//calculate the maximum value of the new list
        
        if(first > max)
            return first;
        else
            return max;
    }
    
    /**
     * 
     * see if the list is empty
     * 
     * @return true if the list is empty. 
     * false if the list isn‘t empty
     */
    public boolean isEmpty() {
        return first == null;
    }
    
    @Override
    public String toString() {
        String s = "";
        
        Node<Item> temp = first;
        
        while(temp != null) {
            Item item = temp.item;
            s += item + " ";
            temp = temp.next;
        }
        
        return s;
    }

    @Override
    public Iterator<Item> iterator() {
        return new ListIterator();
    }
    
    private class ListIterator implements Iterator<Item> {
        
        private Node<Item> current = first;

        @Override
        public boolean hasNext() {
            return current != null;
        }

        @Override
        public Item next() {
            if(!hasNext())
                throw new NoSuchElementException();
            
            Item item = current.item;
            current = current.next;
            
            return item;
        }
        
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
    }
    
}

 

算法(Algorithms)第4版 练习 链表类 1.3.19~1.3.29