數據結構學習 棧 隊列

先進先出的數據結構

接口api

接口抽象定義

public interface AbstractStack<T> {
    void push(T t);
    T pop();
    T peek();
    boolean isEmpty();
    int size();
}

異常類定義

public class StackEmptyException extends RuntimeException{
    public StackEmptyException(String message) {
        super(message);
    }
    public StackEmptyException() {
        super("棧爲空!!!");
    }
}

用數組實現棧

用數組實現棧,這種方法存取數據在沒有擴容時時間複雜是O(1),如果遇到了擴容時間複雜度就變成了O(n),由於擴容的次數會相對的比push的次數少很多,所以push分攤了擴容的時間複雜度

public class ArrayStack<T> implements AbstractStack<T> {

    private final static int DEFAULT_CAPACITY=100;
    T[] stack;
    private int top;

    public ArrayStack() {
        top=0;
        stack= (T[]) new Object[DEFAULT_CAPACITY];
    }

    public ArrayStack(int initalCapacity) {
        top=0;
        stack= (T[]) new Object[initalCapacity];
    }


    @Override
    public void push(T t) {
        if (size()==stack.length){
            expandCapacity();
        }
        stack[top]=t;
        top++;
    }

    private void expandCapacity() {
        Arrays.copyOf(stack,stack.length*2);
    }

    @Override
    public T pop() throws StackEmptyException{
        if (isEmpty()){
            throw new StackEmptyException();
        }
        T result=stack[top];
        stack[top]=null;
        top--;
        return result;
    }

    @Override
    public T peek() throws StackEmptyException {
        if (size()<=0){
            throw new StackEmptyException();
        }
        return stack[top-1];
    }

    @Override
    public boolean isEmpty() {
        return stack.length>0?false:true;
    }

    @Override
    public int size() {
        return stack.length;
    }
}

用鏈表實現棧

用鏈表實現棧,雖然不存在擴容,存取都是O(1),但是會使用跟多的空間,屬於空間換時間的做法

public class LinkedStack<T> implements AbstractStack<T> {

    private LinkedNode<T> top;

    private int count;

    public LinkedStack() {
        top=null;
        count=0;
    }

    @Override
    public void push(T t) {
        LinkedNode<T> node=new LinkedNode<>(t);
        node.setNext(top);
        top=node;
        count++;
    }

    @Override
    public T pop() throws StackEmptyException{
        if (isEmpty()){
            throw new StackEmptyException();
        }
        T element = top.getElement();
        top=top.getNext();
        count--;
        return element;
    }

    @Override
    public T peek() throws StackEmptyException{
        if (isEmpty()){
            throw new StackEmptyException();
        }
        return top.getElement();
    }

    @Override
    public boolean isEmpty() {
        return size()>0?false:true;
    }

    @Override
    public int size() {
        return count;
    }


    class LinkedNode<T>{
        private LinkedNode<T> next;
        private T element;

        public LinkedNode() {
            next=null;
            element=null;
        }

        public LinkedNode(T element) {
            next=null;
            this.element = element;
        }

        public T getElement() {
            return element;
        }

        public void setElement(T element) {
            this.element = element;
        }

        public void setNext(LinkedNode<T> next) {
            this.next = next;
        }

        public LinkedNode<T> getNext() {
            return next;
        }
    }
}

隊列

一個先進後出的數據結構,也可以說是先來後到或者先到先得

接口ap

接口抽象定義

public interface AbstrackQueue<T> {
    void enqueue(T element);
    T dequeue();
    int size();
    boolean isEmpty();
    T first();
}

異常類定義

public class QueueEmptyException extends RuntimeException {
    public QueueEmptyException() {
        super("隊列爲空!!!!");
    }
    public QueueEmptyException(String message) {
        super(message);
    }
}

用鏈表實現隊列

存取都是O(1),但是使用了更多的空間

public class LinkedQueue<T> implements AbstrackQueue<T> {

    private int count;

    private LinkedNode<T> head,tail;

    public LinkedQueue() {
        count=0;
        head=tail=null;
    }

    @Override
    public void enqueue(T element) {
        LinkedNode<T> node=new LinkedNode<>(element);
        if (isEmpty()){
            head=node;
        }else {
            tail.setNext(node);
        }
        tail=node;
        count++;
    }

    @Override
    public T dequeue() throws QueueEmptyException{
        if (isEmpty()){
            throw new QueueEmptyException();
        }
        T result = head.element;
        head=head.getNext();
        count++;
        if (isEmpty()){
            tail=null;
        }
        return result;
    }

    @Override
    public int size() {
        return count;
    }

    @Override
    public boolean isEmpty() {
        return size()>0?false:true;
    }

    @Override
    public T first() throws QueueEmptyException{
        if (isEmpty()){
            throw new  QueueEmptyException();
        }
        return head.getElement();
    }

    class LinkedNode<T>{
        private LinkedNode<T> next;
        private T element;

        public LinkedNode() {
            next=null;
            element=null;
        }

        public LinkedNode(T element) {
            next=null;
            this.element = element;
        }

        public T getElement() {
            return element;
        }

        public void setElement(T element) {
            this.element = element;
        }

        public void setNext(LinkedNode<T> next) {
            this.next = next;
        }

        public LinkedNode<T> getNext() {
            return next;
        }
    }
}

使用數組實現隊列(循環隊列)

使用數組需要考慮的是數組移動的問題,每當dequeue一個元素時,數組都得往前移動n-1個位置,這樣效率太低了,所以使用環形數組的形式


公式:front代表隊列的首元素存儲的位置,rear是數組的下一個可用的數組下標,arrays是數組,index=(index+1)%arrays.length,當rear爲0時,代表了數組已經被填充滿了

public class ArrayQueue<T> implements AbstrackQueue<T> {

    private final static int DEFAULT_CAPACITY=100;
    private int front,rear,count;
    private T[] queque;

    public ArrayQueue() {
        this(DEFAULT_CAPACITY);
        front=rear=count=0;
    }

    public ArrayQueue(int initialCapacity) {
        front=rear=count=0;
        queque= (T[]) new Object[initialCapacity];
    }

    @Override
    public void enqueue(T element) {
        if (size()==queque.length){
            expandCapacity();
        }
        queque[rear]=element;
        rear=(rear+1)%queque.length;
        count++;
    }

    private void expandCapacity() {
        T[] newCapacity= (T[]) new Object[queque.length*2];
        for (int i=0;i<count;i++){
            newCapacity[i]=queque[front];
            front=(front+1)%queque.length;
        }
        front=0;
        rear=count;
    }

    @Override
    public T dequeue() throws QueueEmptyException{
        if (isEmpty()){
            throw new QueueEmptyException();
        }
        T result = queque[front];
        queque[rear]=null;
        front=(front+1)%queque.length;
        count--;
        return result;
    }

    @Override
    public int size() {
        return count;
    }

    @Override
    public boolean isEmpty() {
        return size()>0?false:true;
    }

    @Override
    public T first() {
        return queque[front];
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章