玩转数据结构<二>栈和队列

栈 Stack

  • 栈也是一种线性结构数组

  • 相比数组,栈对应的操做是数组的子集bash

  • 只能从一端添加元素,也只能从一端取出元素数据结构

  • 这一端称为栈顶app

  • 栈是一种后进先出的结构(Last In First Out LIFO)dom

  • 栈的应用编辑器

  • 无处不在的Undo操做(撤销) ide

  • 程序调用的系统栈oop

栈的实现

  • 代码实现性能

  • 接口代码测试

public interface Stack<E> {
    int getSize();
    boolean isEmpty();
    void  push(E e);
    E pop();
    E peek();
}
复制代码
  • 实现类
public class ArrayStack<E> implements Stack<E> {

    Array<E> array;

    public ArrayStack(int capacity){
        array = new Array<>(capacity);
    }

    public ArrayStack(){
        array = new Array<>();
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    @Override
    public void push(E e) {
        array.addLast(e);

    }

    @Override
    public E pop() {
        return array.removeLast();
    }

    @Override
    public E peek() {
        return array.getLast();
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("Stack: ");
        res.append('[');
        for(int i = 0 ; i < array.getSize(); i++) {
            res.append(array.get(i));
            if (i != array.getSize() - 1) {
                res.append(",");
            }
        }
            res.append("] top");
            return res.toString();
        }


    public int getCapacity(){
        return array.getCapacity();
    }


}

复制代码
  • 调用栈方法
ArrayStack<Integer> stack = new ArrayStack<>();
       for(int i = 0 ; i < 5 ; i++){
           stack.push(i);
           System.out.println(stack);
       }

       stack.pop();
       System.out.println(stack);
    }
复制代码
  • 栈的时间复杂度分析

栈的应用

  • undo操做 - 编辑器
  • 系统调用栈 - 操做系统
  • 括号匹配 - 编译器
class Solution{
    public boolean isValid(String s){
        Stack<Character> stack = new Stack<>();
        for(int i = 0 ; i < s.length(); i++){
            char c = s.charAt(i);
            if(c == '(' || c ==  '[' || c == '{'){
                stack.push(c);
            }else{
                if(stack.isEmpty()){
                    return false;
                }
                char topChar = stack.pop();
                if(c == ')' && topChar != '('){
                    return false;
                }
                 if(c == ']' && topChar != '['){
                    return false;
                }
                 if(c == '}' && topChar != '{(}'){
                    return false;
                }
            }
        } 
        return stack.isEmpty();
    }
}
复制代码

队列(Queue)

  • 队列也是一种线性结构
  • 相比数组,队列对应的操做是数组的子集
  • 只能从一端(队尾)添加元素,只能从另外一端(队首)去吃元素
  • 队列是一种先进先出的数据结构(先到先得)
  • First In First Out (FIFO)

public class ArrayQueue<E> implements Queue<E> {

    private  Array<E> array;

    public  ArrayQueue(int capacity){
        array = new Array<>(capacity);
    }

    public  ArrayQueue(){
        array = new Array<>();
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    public int getCapacity(){
        return array.getCapacity();
    }

    @Override
    public void enQueue(E e) {
        array.addLast(e);
    }

    @Override
    public E dequeue() {
        return array.removeFirst();
    }

    @Override
    public E getFront() {
        return array.getFirst();
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("Queue: ");
        res.append("front [");
        for(int i = 0 ; i < array.getSize(); i++) {
            res.append(array.get(i));
            if (i != array.getSize() - 1) {
                res.append(",");
            }
        }
        res.append("] tail");
        return res.toString();
    }

    public static void main(String[] args){
        ArrayQueue<Integer> queue = new ArrayQueue<>();
        for(int i = 0 ; i < 10 ; i++){
            queue.enQueue(i);
            System.out.println(queue);
            if(i % 3 == 2){
                queue.dequeue();
                System.out.println(queue);
            }
        }

    }
}


复制代码

循环队列

  • 代码实现
public class LoopQueue<E> implements Queue<E> {

    private E[] data;
    private int front, tail;
    private int size;

    public  LoopQueue(int capacity){
        data = (E[])new Object[capacity + 1];
        front = 0;
        tail = 0;
        size = 0;
    }

    public  LoopQueue(){
        this(10);
    }
    public int getCapacity(){
        return data.length - 1;
    }

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

    @Override
    public boolean isEmpty() {
        return front == tail;
    }

    @Override
    public void enqueue(E e) {
            if((tail+1) % data.length == front){
                resize(getCapacity() * 2);
            }
            data[tail] = e;
            tail = (tail + 1)% data.length;
            size ++;
    }

    private void resize(int newCapacity){
        E[] newData = (E[]) new Object[newCapacity + 1];
        for(int i = 0;i < size ;i++){
            newData[i] =data[(front + i) % data.length];
        }
        data = newData;
        front = 0;
        tail = size;
    }

    @Override
    public E dequeue() {
        if(isEmpty()){
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        }
        E ret = data[front];
        data[front] = null;
        front =(front + 1) % data.length;
        size --;
        if(size == getCapacity()/4 && getCapacity() /2 != 0){
            resize(getCapacity() /2);
        }
        return ret;
    }

    @Override
    public E getFront() {
        if(isEmpty()){
            throw new IllegalArgumentException("Queue is empty.");
        }
        return data[front];
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity()));
        res.append(" front[" );
        for(int i = front ; i != tail ; i = ( i + 1 ) % data.length ){
            res.append(data[i]);
            if((i + 1) % data.length != tail){
                res.append(",");
            }
        }
        res.append("]tail");
        return res.toString();
    }

    public static void main(String[] args){
        LoopQueue<Integer> queue = new  LoopQueue<>();
        for(int i = 0 ; i < 10 ; i++){
            queue.enqueue(i);
            System.out.println(queue);
            if(i % 3 == 2){
                queue.dequeue();
                System.out.println(queue);
            }
        }

    }
}

复制代码
  • loopQueue与ArrayQueue的性能对比
  • 代码
public class Main {
    //测试使用q运行opCount个enqueue和dequeue操做所须要的时间,单位:秒
    private static double testQueue(Queue<Integer> q, int opCount){
        long startTime = System.nanoTime();
        Random random = new Random();
        for(int i = 0 ;i < opCount; i++){
            q.enqueue(random.nextInt(Integer.MAX_VALUE));
        }

        for(int i = 0 ;i < opCount; i++) {
            q.dequeue();
        }

        long endTime = System.nanoTime();
        return(endTime - startTime) / 1000000000.0;

    }
    public static void main(String[] args) {

      int opCount = 100000;

      ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();
      double time1 = testQueue(arrayQueue,opCount);
      System.out.println("ArrayQueue,time: "+ time1 +"s");
      LoopQueue<Integer> loopQueue = new LoopQueue<>();
      double time2 = testQueue(loopQueue,opCount);
      System.out.println("LoopQueue,time: "+ time2 +"s");

    }
}
复制代码
  • 对比结果

相关文章
相关标签/搜索