import java.util.Iterator;
import java.util.NoSuchElementException; public class List<Item> implements Iterable<Item>
{
private int N;
private Node first;
private Node last; private class Node
{
private Item item;
private Node next;
} public List()
{
first = null;
last = null;
} public List(Item[] a)
{
for (Item t : a)
append(t);
} public List(Iterable<Item> coll)
{
for (Item t : coll)
append(t);
} public boolean isEmpty()
{
return first == null;
} public int size()
{
return N;
} public Item first()
{
if (isEmpty()) throw new RuntimeException("List is empty");
return first.item;
} public Item last()
{
if (isEmpty()) throw new RuntimeException("List is empty");
return last.item;
} public Item removeFirst()
{
if (isEmpty()) throw new RuntimeException("List is empty");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null; // to avoid loitering
return item;
} public void prepend(Item item)
{
Node x = new Node();
x.item = item;
if (isEmpty()) { first = x; last = x; }
else { x.next = first; first = x; }
N++;
} public void append(Item item)
{
Node x = new Node();
x.item = item;
if (isEmpty()) { first = x; last = x; }
else { last.next = x; last = x; }
N++;
} public String toString()
{
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
} public Iterator<Item> iterator()
{
return new ListIterator();
} private class ListIterator implements Iterator<Item>
{
private Node current = first; public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); } public Item next()
{
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
} /*****************
* Exercise 1.3.19
*****************/
public Item removeLast()
{
if (isEmpty()) throw new RuntimeException("List is empty");
if (first == last) return removeFirst();
Item item = last.item; Node prev = null,
curr = first;
while (curr.next != null)
{
prev = curr;
curr = curr.next;
}
prev.next = null;
last = prev;
N--; return item;
} /*****************
* Exercise 1.3.20
*****************/
public Item delete(int k)
{
if (k < 1) return null; int i = 1;
Node prev = null,
curr = first; while (i < k && curr != null)
{
prev = curr;
curr = curr.next;
i++;
} if (curr != null)
{
if (prev == null)
first = curr.next;
else
prev.next = curr.next; if (curr.next == null)
last = prev; N--;
return curr.item;
}
else
return null;
} /*************************************
* Exercise 1.3.21
* (Renamed from find() to contains())
*************************************/
public boolean contains(Item item)
{
Node curr = first;
while (curr != null && !curr.item.equals(item))
curr = curr.next;
return curr != null;
} /*****************
* Exercise 1.3.26
*****************/
public void remove(Item item)
{
List<Integer> idx = new List<Integer>();
int i = 1; for (Item x : this)
{
if (x.equals(item))
idx.prepend(i);
i++;
} for (int k : idx)
delete(k);
} /***************************************
* Recursive solution to Exercise 1.3.26
***************************************/
public void removeRec(Item item)
{
first = remove_Node(first, item);
setLastAndN();
} private Node remove_Node(Node node, Item item)
{
if (node != null)
{
Node rest = remove_Node(node.next, item); if (node.item.equals(item))
return rest;
else
{
node.next = rest;
return node;
}
}
else
return null;
} private void setLastAndN()
{
last = first;
N = 0;
if (first != null)
{
N++;
while (last.next != null)
{
last = last.next;
N++;
}
}
} /*********************
* Operations on nodes
*********************/ public Node node(int k)
{
if (k < 1) return null; int i = 1;
Node curr = first; while (i < k && curr != null)
{
curr = curr.next;
i++;
} return curr;
} public Node createNode(Item item)
{
Node node = new Node();
node.item = item;
return node;
} /*****************
* Exercise 1.3.24
*****************/
public void removeAfter(Node node)
{
if (node != null && node.next != null)
{
if (node.next.next == null)
last = node;
node.next = node.next.next;
N--;
}
} /*****************
* Exercise 1.3.25
*****************/
public void insertAfter(Node a, Node b)
{
if (a != null && b != null)
{
if (last == a)
last = b;
b.next = a.next;
a.next = b;
N++;
}
} /*************************************************
* Exercise 1.3.27
* Type 'Item' must implement interface Comparable
*************************************************/
public Item max(Node node)
{
if (node == null) throw new RuntimeException("List is empty");
return max(node, null);
} public Item max(Node node, Item def)
{
if (node == null)
return def; Item max = node.item;
Node curr = node; while (curr.next != null)
{
curr = curr.next;
if (((Comparable)max).compareTo(curr.item) < 0)
max = curr.item;
} return max;
} /*************************************************
* Exercise 1.3.28
* (recursive variant of Exercise 1.3.27)
* Type 'Item' must implement interface Comparable
*************************************************/
public Item maxRec(Node node, Item def)
{
if (node == null)
return def;
else
return maxRec(node);
} public Item maxRec(Node node)
{
if (node == null) throw new RuntimeException("List is empty"); if (node.next == null)
return node.item;
else
{
Item maxTail = maxRec(node.next);
return ((Comparable)node.item).compareTo(maxTail) > 0 ? node.item : maxTail;
}
} /*****************
* Exercise 1.3.30
*****************/
public void reverse()
{
first = reverse(first);
setLastAndN();
} public Node reverse(Node node)
{
Node srcFirst = node,
destFirst = null;
while (srcFirst != null)
{
Node next = srcFirst.next;
srcFirst.next = destFirst;
destFirst = srcFirst;
srcFirst = next;
} return destFirst;
} /***************************************
* Recursive solution to Exercise 1.3.30
***************************************/
public void reverseRec()
{
first = reverseRec(first);
setLastAndN();
} private Node reverseRec(Node node)
{
return reverseRec(node, null);
} private Node reverseRec(Node srcFirst, Node destFirst)
{
if (srcFirst == null)
return destFirst;
else
{
Node next = srcFirst.next;
srcFirst.next = destFirst;
return reverseRec(next, srcFirst);
}
} /************
* Unit tests
************/ private static void testBaseMethods()
{
int[] a = { 2, 4, 6, 8, 10, 12 }; List<Integer> lst = new List<Integer>();
for (int i = 0; i < a.length; i++)
lst.append(a[i]);
showList(lst); lst = new List<Integer>();
for (int i = 0; i < a.length; i++)
lst.prepend(a[i]);
showList(lst); StdOut.println("removeFirst: " + lst.removeFirst());
showList(lst);
} private static void testRemoveLast()
{
List<Integer> lst = new List<Integer>(new Integer[] { 6, 8, 10, 12 });
showList(lst); while (!lst.isEmpty())
{
StdOut.println("removeLast: " + lst.removeLast());
showList(lst);
}
} private static void testDelete()
{
List<Integer> lst = new List<Integer>(new Integer[] { 2, 4, 6, 8, 10, 12 });
showList(lst); StdOut.printf("delete(%d): %s\n", 5, lst.delete(5));
showList(lst); StdOut.printf("delete(%d): %s\n", 1, lst.delete(1));
showList(lst); StdOut.printf("delete(%d): %s\n", 4, lst.delete(4));
showList(lst); StdOut.printf("delete(%d): %s\n", 8, lst.delete(8));
showList(lst); StdOut.printf("delete(%d): %s\n", 0, lst.delete(0));
showList(lst); while (!lst.isEmpty())
{
StdOut.printf("delete(%d): %s\n", 1, lst.delete(1));
showList(lst);
}
} private static void testContains()
{
Integer[] a = { 4, 6, 10, 12 };
List<Integer> lst = new List<Integer>(a);
showList(lst); StdOut.printf("contains(%d): %s\n", 0, lst.contains(0)); for (int i = 0; i < a.length; i++)
StdOut.printf("contains(%d): %s\n", a[i], lst.contains(a[i]));
} private static void testRemove()
{
for (int k = 0; k < 8; k++)
{
List<Integer> lst1 = randomList(20, 0, 5);
List<Integer> lst2 = new List<Integer>(lst1);
StdOut.println(lst1);
StdOut.println(); int n = StdRandom.uniform(0, 5); StdOut.printf("remove(%d):\n", n);
lst1.remove(n);
showList(lst1); StdOut.printf("removeRec(%d):\n", n);
lst2.removeRec(n);
showList(lst2);
StdOut.println();
}
} private static void testReverse()
{
int n = 10;
Integer[] a = new Integer[n];
for (int i = 0; i < n; i++)
a[i] = 2 * (i + 1); testReverse(new List<Integer>(a));
StdOut.println(); testReverse(randomList(20, 0, 10));
StdOut.println(); testReverse(new List<Integer>(new Integer[] { 37 }));
StdOut.println(); testReverse(new List<Integer>(new Integer[] { }));
StdOut.println();
} private static void testReverse(List<Integer> lst)
{
List<Integer> lst1 = lst;
List<Integer> lst2 = new List<Integer>(lst1);
StdOut.println(lst1); StdOut.println("reverse():");
lst1.reverse();
StdOut.println(lst1); StdOut.println("reverseRec():");
lst2.reverseRec();
StdOut.println(lst2);
} private static void testNode()
{
List<Integer> lst = new List<Integer>(new Integer[] { 2, 6, 12 });
showList(lst); for (int i = -1; i <= 4; i++)
StdOut.printf("node(%d): %s\n", i, lst.node(i) != null ? lst.node(i).item : null);
} private static void testRemoveAfter()
{
List<Integer> lst = new List<Integer>(new Integer[] { 2, 6, 8, 10, 12 });
showList(lst); int[] k = { 0, 2, 1, 5, 3, 2, 1 }; for (int i = 0; i < k.length; i++)
{
StdOut.printf("removeAfter(node(%d)):\n", k[i]);
lst.removeAfter(lst.node(k[i]));
showList(lst);
}
} private static void testInsertAfter()
{
List<Integer> lst = new List<Integer>(new Integer[] { 2, 6, 10, 12 });
showList(lst); StdOut.printf("insertAfter(node(%d), null):\n", 1);
lst.insertAfter(lst.node(1), null);
showList(lst); int ia = 1,
b = 3;
StdOut.printf("insertAfter(node(%d), createNode(%d)):\n", ia, b);
lst.insertAfter(lst.node(ia), lst.createNode(b));
showList(lst); ia = 5;
b = 25;
StdOut.printf("insertAfter(node(%d), createNode(%d)):\n", ia, b);
lst.insertAfter(lst.node(ia), lst.createNode(b));
showList(lst);
} private static void testMax()
{
for (int k = 0; k < 8; k++)
{
List<Integer> lst = randomList(10, 100, 1000);
StdOut.println(lst); StdOut.printf("max(): %d\n", lst.max(lst.node(1)));
StdOut.printf("maxRec(): %d\n\n", lst.maxRec(lst.node(1)));
}
} /*******************
* Unit test helpers
*******************/ public static void showList(List lst)
{
StdOut.println(lst);
if (!lst.isEmpty())
StdOut.printf("Size: %d, First: %s, Last: %s\n\n", lst.size(), lst.first(), lst.last());
else
StdOut.printf("Size: %d\n\n", lst.size());
} private static List<Integer> randomList(int n, int a, int b)
{
Integer[] r = new Integer[n];
for (int i = 0; i < n; i++)
r[i] = StdRandom.uniform(a, b);
return new List<Integer>(r);
} public static void main(String[] args)
{
testBaseMethods();
StdOut.println(); testRemoveLast();
StdOut.println(); testDelete();
StdOut.println(); testContains();
StdOut.println(); testNode();
StdOut.println(); testRemoveAfter();
StdOut.println(); testInsertAfter();
StdOut.println(); testRemove();
StdOut.println(); testMax();
StdOut.println(); testReverse();
StdOut.println();
}
}

算法Sedgewick第四版-第1章基础-016一list的更多相关文章

  1. 算法Sedgewick第四版-第1章基础-001递归

    一. 方法可以调用自己(如果你对递归概念感到奇怪,请完成练习 1.1.16 到练习 1.1.22).例如,下面给出了 BinarySearch 的 rank() 方法的另一种实现.我们会经常使用递归, ...

  2. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-001选择排序法(Selection sort)

    一.介绍 1.算法的时间和空间间复杂度 2.特点 Running time is insensitive to input. The process of finding the smallest i ...

  3. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-007归并排序(自下而上)

    一. 1. 2. 3. 二.代码 package algorithms.mergesort22; import algorithms.util.StdIn; import algorithms.uti ...

  4. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-006归并排序(Mergesort)

    一. 1.特点 (1)merge-sort : to sort an array, divide it into two halves, sort the two halves (recursivel ...

  5. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-005插入排序的改进版

    package algorithms.elementary21; import algorithms.util.StdIn; import algorithms.util.StdOut; /***** ...

  6. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-004希尔排序法(Shell Sort)

    一.介绍 1.希尔排序的思路:希尔排序是插入排序的改进.当输入的数据,顺序是很乱时,插入排序会产生大量的交换元素的操作,比如array[n]的最小的元素在最后,则要经过n-1次交换才能排到第一位,因为 ...

  7. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-002插入排序法(Insertion sort)

    一.介绍 1.时间和空间复杂度 运行过程 2.特点: (1)对于已排序或接近排好的数据,速度很快 (2)对于部分排好序的输入,速度快 二.代码 package algorithms.elementar ...

  8. 算法Sedgewick第四版-第1章基础-1.3Bags, Queues, and Stacks-001可变在小的

    1. package algorithms.stacks13; /******************************************************************* ...

  9. 算法Sedgewick第四版-第1章基础-1.4 Analysis of Algorithms-005计测试算法

    1. package algorithms.analysis14; import algorithms.util.StdOut; import algorithms.util.StdRandom; / ...

随机推荐

  1. LeetCode OJ:Serialize and Deserialize Binary Tree(对树序列化以及解序列化)

    Serialization is the process of converting a data structure or object into a sequence of bits so tha ...

  2. shell编程-条件判断与流程控制

    1.条件判断式 按照文件类型进行判断: 两种判断格式: test -e /root/install.log [ -e /root/install.log ] 判断命令是否正确执行: [ -d /roo ...

  3. 团队队列(列和map结合的经典运用)

    Queues and Priority Queues are data structures which are known to most computer scientists. The Team ...

  4. php 数组NULL元素的批量处理

    $a = array('a'=>1, 'b'=>0, 'c'=>NULL); foreach($a as $k=>$v) {  // if( is_null($a[$k]))  ...

  5. Gradle的快速入门

    1.基础知识: Gradle提供了:构建项目的框架.但是其中起作用的是Plugin. Gradle在默认情况下提供了很多常用的Plugin.例如:构建Java的Plugin.还有war.Ear等. G ...

  6. vim 显示行号

    set nu https://blog.csdn.net/lwj103862095/article/details/8122316

  7. 引用com.sencha.gxt.ui.GXT加载错误解决方案

    环境GWT2.7+GXT4.0 <inherits name='com.sencha.gxt.ui.GXT' /> 出现加载错误 Loading inherited module 'com ...

  8. Day2-Python基础2---字典操作

    一.字典操作 字典一种key - value 的数据类型,使用就像我们上学用的字典,通过笔划.字母来查对应页的详细内容. 语法: 1.基本语法 >>> info = { 'stu11 ...

  9. JPA,EclipseLink 缓存机制学习——树节点搜索问题引发的思考

    最近在项目在使用JPA+EclipseLink 的方式进行开发,其中EclipseLink使用版本为2.5.1.遇到一些缓存方面使用不当造成的问题,从本篇开始逐步学习EclipseLink的缓存机制. ...

  10. 转:InnoDB多版本(MVCC)实现简要分析

    InnoDB多版本(MVCC)实现简要分析 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 InnoDB表数据的组织方 ...