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