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. 32 python 并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  2. [BZOJ1797][AHOI2009]最小割Mincut

    bzoj luogu sol 一条边出现在最小割集中的必要条件和充分条件. 先跑出任意一个最小割,然后在残余网络上跑出\(scc\). 一条边\((u,v)\)在最小割集中的必要条件:\(bel[u] ...

  3. npm镜像安装

    安装淘宝NPM镜像 https://npm.taobao.org/ npm install -g cnpm --registry=https://registry.npm.taobao.org 配置 ...

  4. poj 3463 Sightseeing——次短路计数

    题目:http://poj.org/problem?id=3463 当然要给一个点记最短路和次短路的长度和方案. 但往优先队列里放的结构体和vis竟然也要区分0/1,就像把一个点拆成两个点了一样. 不 ...

  5. 9.Selenium+HTMLTestRunner无法生成测试报告(Pycharm)

    1.若编辑器为Pycharm,代码无任何错误,且运行成功,但是无法生成测试报告,原因如下:(本质是编辑器原因) 若光标在如图位置,右键显示为“run 'unittest in XX'”,若是显示这种, ...

  6. Ubuntu 16.04安装Elasticsearch,Logstash和Kibana(ELK)Filebeat

    https://www.howtoing.com/how-to-install-elasticsearch-logstash-and-kibana-elk-stack-on-ubuntu-16-04 ...

  7. Poj 2395 Out of Hay( 最小生成树 )

    题意:求最小生成树中最大的一条边. 分析:求最小生成树,可用Prim和Kruskal算法.一般稀疏图用Kruskal比较适合,稠密图用Prim.由于Kruskal的思想是把非连通的N个顶点用最小的代价 ...

  8. CPU 和 Linux 进程

    进程与线程 进程应该是Linux中最重要的一个概念.进程运行在CPU上,是所有硬件资源分配的对象.Linux中用一个task_struct的结构来描述进程,描述了进程的各种信息.属性.资源. Linu ...

  9. 获得Oracle中刚插入的数据的ID(for produce)

    在sql sever中实现插入数据的自动增长是很容易的,但是在oracle数据库中实现这一操作不是很容易,同时要想在.net中实现获取新插入数据的id,而 且不会出现读错的情况,就更显得困难了,为了解 ...

  10. JSP/java 执行创建批处理文件,并执行批处理事务。

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) { InputStream in = null; Inpu ...