Algorithms 4th Reading Note(1:Foundation)

1.定容栈

public class StringArrayOfStack {
  private String[] stack;
  private int size;
  public StringArrayOfStack(int cap){
    stack=new String[cap];
    size=0;
  }

  public boolean isEmpty(){
    return size==0;
  }

  public int size(){
    return size;
  }

  public void push(String item){
    stack[size++]=item;
  }

  public String pop(){
    return stack[--size];
  }
}

2.泛型定容栈

public class FixedCapacityStackOfStrings<Item> {
    private Item[] s;
    private int N = 0;

    @SuppressWarnings("unchecked")
    public FixedCapacityStackOfStrings(int capacity) {
        s = (Item[]) new Object[capacity];
    }

    public boolean isEmpty() {
        return N == 0;
    }

    public void push(Item item) {
        if (N == s.length) {
            resize(2 * s.length);
        }
        s[N++] = item;
    }

    public Item pop() {
        Item item = s[--N];
        s[N] = null;
        if (N == s.length / 4 && N > 0) {
            resize(s.length / 2);
        }
        return item;
    }

    public int size() {
        return N;
    }

  在这里有一个细节非常重要:我们希望用以上代码的构造函数的实现中创建一个泛型的数组:

a=new Item[cap];

  由于某些历史和技术原因,创建泛型数组在Java中是不允许的。我们需要类型转换

a=(Item []) new Object[cap];

  

3.调整数组大小

  选择用数组表示栈内容意味着用例必须预先估计栈的最大容量。在Java中,数组一旦创建,其大小是无法改变的,因此栈使用的空间只能是这个最大容量的一部分。选择大容量的用例在栈为空或几乎为空时会浪费大量的内存。另一方面,如果集合变得比数组更大那么用例有可能溢出。

  动态调整数组s[]的大小,使得它既足以保存所有元素,又不至于浪费过多的空间。

  首先,实现一个方法讲栈移动到另一个大小不同的数组中

public void resize(int Max) {
        Item[] item = (Item[]) new Object[Max];
        for (int i = 0; i < N; i++) {
            item[i] = s[i];
        }
        s = item;
    }

  现在,在push()中,检查数组是否太小。具体来说,我们会通过检查栈大小N和数组大小a.length是否想等来检查数组是否能够容纳新的元素。如果没有多余的空间,我们会将数组的长度加倍。然后就可以和从前一样使用s[N++]=item插入新元素了。

public void push(Item item) {
        if (N == s.length) {
            resize(2 * s.length);
        }
        s[N++] = item;
    }

  类似,在pop()中,首先删除栈顶的元素,然后如果数组太大我们就将它的长度减半。只要稍加思考,你就明白正确的检测条件是栈大小是否小于数组的四分之一。在数组长度被减半之后,它的状态约为半满,在下次需要改变数组大小之前仍然能够进行多次push()和pop()操作

public Item pop() {
        Item item = s[--N];
        s[N] = null;
        if (N == s.length / 4 && N > 0) {
            resize(s.length / 2);
        }
        return item;
    }

  在这个实现中,栈永远不会溢出,使用率也永远不会低于四分之一(除非栈为空,那种情况下数组的大小为1)

4.迭代

  在任意可迭代的集合数据类型中我们都需要实现的东西:

  1)集合数据类型必须实现一个iterator()方法并返回一个Iterator对象。

  2)Iterator类必须包含两个方法:hasNext()(返回一个布尔值)和next()(返回集合中的一个泛型元素)。

  

  在Java中,我们使用接口机制来指定一个类所必须实现的方法。对于可迭代的集合数据类型,Java已经为我们定义了所需的接口。

  要使一个类可迭代,第一步就是在它的声明中加入implements Iterable<Item>,对应的接口为:

public interface Iterable<Item>{
    Iterator<Item> iterator();
}

  然后在类中添加一个方法iterator()并返回一个迭代器Iterator<Item>。迭代器都是泛型的,因此我们可以使用参数类型Item来帮助用例遍历它们指定的任意类型的对象。对于一直使用的数组表示法,我们需要逆序迭代遍历这个数组,因此我们将迭代器命名为ReverseArrayIterator,并添加方法:

public Iterator<Item> iterator(){
    return new ReverseArrayIterator();
}

  迭代器是什么?它是一个实现了hasNext()和next()方法的类的对象,由以下接口定义

public interface Iterator<Item>{
    public boolean hasNext(){return i>0;}
    public Item next(){return a[--i];}
    public void remove(){ }
}

  尽管接口指定了一个remove()方法,但在本书中remove()方法总为空,因为我们希望避免在迭代中穿插能够修改数据结构的操作。对于ReverseArrayIterator,这些方法只需要一行代码,它们实现在栈类的一个嵌套类中:

private class ReverseArrayIterator implements Iterator<Item> {
        private int i = N;


        @Override
        public boolean hasNext() {
            return i > 0;
        }

        @Override
        public Item next() {
            return s[--i];
        }

        @Override
        public void remove() {
        }
    }

  请注意,嵌套类可以访问包含它的类的实例变量,在这里就是s[]和N(这也是我们使用嵌套类实现迭代器的主要原因)。从技术角度来说,为了和Iterator的结构保持一致,我们应该在两种情况下抛出异常:如果用例调用了remove()则抛出UnsupportedOperationException,如果用例在调用next()时i为0则抛出NoSuchElementException。因为我们只会在foreach语法中使用迭代器,这些情况都不会出现,所以我们省略了这部分代码

5.链表

  使用一个嵌套类来定义结点的抽象数据类型

private class Node{
    Item item;
    Node next;
}

  链表的使用能达到三个设计目标:

  1)它可以处理任意类型的数据。

  2)所需的空间总是和集合的大小成正比。

  3)操作所需的时间总是和集合的大小无关。

  下压堆栈(链表实现)

public class LinkedlistOfStack<Item> implements Iterable<Item> {

  private int size;
  private Node first;

  private class Node {

    Item item;
    Node next;
  }

  public boolean isEmpty() {
    return first == null;
  }

  public int size() {
    return size;
  }

  public void push(Item item) {
    Node old = first;
    first = new Node();
    first.item = item;
    first.next = old;
    size++;
  }

  public Item pop() {
    Item item = first.item;
    first = first.next;
    size--;
    return item;
  }

  public Iterator<Item> iterator() {
    return new ReverseStack();
  }

  private class ReverseStack implements Iterator<Item> {

    private Node pointer = first;

    public boolean hasNext() {
      return pointer != null;
    }

    public Item next() {
      Item item = pointer.item;
      pointer = pointer.next;
      return item;
    }

    public void remove() {
    }
  }
}

  队列的实现

public class LinkedQueueOfStrings<Item> implements Iterable<Item> {
    private Node first;
    private Node last;
    private int N;

    private class Node {
        Item item;
        Node next;
    }

    public boolean isEmpty() {
        return first == null;
    }

    public int size() {
        return N;
    }

    public void enqueue(Item item) {
        Node oldlast = new Node();
        last = new Node();
        last.item = item;
        if (isEmpty()) {
            first = last;
        } else {
            oldlast.next = last;
        }
        N++;
    }

    public Item dequeue() {
        Item item = first.item;
        first = first.next;
        if (isEmpty()) {
            last = null;
        }
        N--;
        return item;
    }

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

        public Item next() {
            Item item = current.item;
            current = current.next;
            return item;
        }
    }
}

  背包的实现

public class Bag<Item> implements Iterable<Item> {
    private Node first;

    private class Node {
        Item item;
        Node next;
    }

    public void add(Item item) {
        Node oldfirst = first;
        first = new Node();
        first.item = item;
        first.next = oldfirst;
    }

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

        public Item next() {
            Item item = current.item;
            current = current.next;
            return item;
        }
    }
}

6.union-find算法

  

原文地址:https://www.cnblogs.com/Miromiaosang/p/8542471.html