1. 程式人生 > >溫習Algs4 (一):揹包, 棧, 佇列和線性表

溫習Algs4 (一):揹包, 棧, 佇列和線性表

揹包, 棧, 佇列和線性表

揹包

揹包是最簡單的資料結構, 只有新增資料遍歷元素兩個功能, 內部實現是連結串列.

Bag.java

/******************************************************************************
 *  Compilation:  javac Bag.java
 *  Execution:    java Bag
 *  Author:       Chenghao Wang
 ******************************************************************************/
import java.util.Iterator; import java.util.NoSuchElementException; public class Bag<T> implements Iterable<T> { private class Node { private T item; private Node next; Node(T item) { this.item = item; next = null; } } private
class BagIterator implements Iterator<T> { private Node current = head; @Override public boolean hasNext() { return current != null; } @Override public T next() { if (current == null) throw new NoSuchElementException()
; T result = current.item; current = current.next; return result; } @Override public void remove() { throw new UnsupportedOperationException(); } } private Node head = null; public void add(T item) { Node n = new Node(item); n.next = head; head = n; } @Override public Iterator<T> iterator() { return new BagIterator(); } }

複雜度分析

  • add: O(1)

棧支援的功能有壓棧, 出棧, 查詢棧頂元素, 檢查是否為空和查詢元素個數. 內部實現也是連結串列.

Stack.java

/******************************************************************************
 *  Compilation:  javac Stack.java
 *  Execution:    java Stack
 *  Author:       Chenghao Wang
 ******************************************************************************/

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

public class Stack<T> implements Iterable<T> {

    private class Node {
        private T item;
        private Node next;

        Node(T item) {
            this.item = item;
            next = null;
        }
    }

    private class StackIterator implements Iterator<T> {
        private Node current = head;

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

        @Override
        public T next() {
            if (current == null) throw new NoSuchElementException();
            T result = current.item;
            current = current.next;
            return result;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private Node head = null;
    private int size = 0;

    public void push(T item) {
        Node n = new Node(item);
        n.next = head;
        head = n;
        size++;
    }

    public T pop() {
        if (size == 0) {
            throw new NoSuchElementException();
        }

        size--;
        T result = head.item;
        head = head.next;
        return result;
    }

    public T top() {
        if (size == 0) {
            throw new NoSuchElementException();
        }
        return head.item;
    }

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

    public int size() {
        return size;
    }

    public Iterator<T> iterator() {
        return new StackIterator();
    }
}

複雜度分析

  • push: O(1)
  • pop: O(1)
  • isEmpty: O(1)
  • size: O(1)

佇列

佇列支援的功能有入列, 出列, 檢查是否為空和查詢元素個數. 內部實現也是連結串列.

Queue.java

/******************************************************************************
 *  Compilation:  javac Queue.java
 *  Execution:    java Queue
 *  Author:       Chenghao Wang
 ******************************************************************************/

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

public class Queue<T> implements Iterable<T> {

    private class Node {
        private T item;
        private Node next;

        Node(T item) {
            this.item = item;
            next = null;
        }
    }

    private class QueueIterator implements Iterator<T> {
        private Node current = head;

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

        public T next() {
            if (current == null) throw new NoSuchElementException();
            T result = current.item;
            current = current.next;
            return result;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private Node head = null;
    private Node tail = null;
    private int size = 0;

    public void enqueue(T item) {
        Node n = new Node(item);
        if (head == null) head = n;
        else tail.next = n;
        tail = n;
        size++;
    }

    public T dequeue() {
        if (size == 0) {
            throw new NoSuchElementException();
        }

        size--;
        T result = head.item;
        head = head.next;
        return result;
    }

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

    public int size() {
        return size;
    }

    public Iterator<T> iterator() {
        return new QueueIterator();
    }
}

複雜度分析

  • enqueue: O(1)
  • dequeue: O(1)
  • isEmpty: O(1)
  • size: O(1)

線性表

線性表即為動態陣列, 支援的方法是對元素的增刪查改, 查詢是否為空和元素個數.

Vector.java

/******************************************************************************
 *  Compilation:  javac Vector.java
 *  Execution:    java Vector
 *  Author:       Chenghao Wang
 ******************************************************************************/

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

public class Vector<T> implements Iterable<T> {

    private class VectorIterator implements Iterator<T> {

        private int ptr = 0;

        @Override
        public boolean hasNext() {
            return ptr < size;
        }

        @Override
        public T next() {
            if (ptr >= size) {
                throw new NoSuchElementException();
            }

            return content[ptr++];
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private static final int INITIAL_CAPACITY = 8;
    private int capacity;
    private int size;
    private T[] content;

    Vector() {
        content = (T[]) new Object[INITIAL_CAPACITY];
        capacity = INITIAL_CAPACITY;
        size = 0;
    }

    void insert(int index, T item) {
        if ((index < 0) || (index > size)) {
            throw new IllegalArgumentException();
        }

        size++;
        for (int i = size - 1; i > index; i++) {
            content[i] = content[i - 1];
        }

        content[index] = item;
        
        if (size == capacity) {
            resize(capacity * 2);
        }
    }

    void add(T item) {
        insert(size, item);
    }

    void remove(int index) {
        if ((index < 0) || (index >= size)) {
            throw new IllegalArgumentException();
        }

        size--;

        for (int i = index; i < size; i++) {
            content[i] = content[i+1];
        }

        if ((size < (capacity / 8)) && (size > 1)) {
            resize(capacity / 4);
        }
    }

    T get(int index) {
        if ((index < 0) || (index >= size)) {
            throw new IllegalArgumentException();
        }

        return content[index];
    }

    void set(int index, T item) {
        if ((index < 0) || (index >= size)) {
            throw new IllegalArgumentException();
        }

        content[index] = item;
    }

    void resize(int c) {
        capacity = c;
        T[] newContent = (T[]) new Object[capacity];
        for (int i = 0; i < size; i++) {
            newContent[i] = content[i];
        }
        content = newContent;
    }

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

    int size() {
        return size;
    }

    @Override
    public Iterator<T> iterator() {
        return new VectorIterator();
    }
}

複雜度分析

  • add: O(1)
  • insert: O(n)
  • remove: O(n)
  • set: O(1)
  • isEmpty: O(1)
  • size: O(1)

總結

最近打算重新複習和鞏固一下基礎演算法, 先從最基本的資料結構入手, 將Algorithms 4th Ed. 的所有演算法和資料結構重新實現一遍.