1. 程式人生 > 其它 >學習筆記:資料結構棧和佇列

學習筆記:資料結構棧和佇列

目錄

一、棧和佇列的共同點

棧和佇列主要作為程式設計師構思演算法的工具,不是完全的資料儲存工具,生命週期比持久型的資料結構短,只有程式執行操作期間才被建立,程式執行完成,就會銷燬。
特性是受限訪問,即不能像陣列那樣直接通過下標訪問元素,也不能像連結串列那樣順序遍歷訪問資料項,特定時刻只能有一個元素被訪問或刪除。

二、棧

1.特性

棧只允許訪問一個數據項:最後插入的資料項。只有移除這個資料項才能訪問倒數第二個被插入的資料項。

2.陣列實現棧

簡單的實現一下棧(用陣列),建立、入棧、出棧、檢視棧頂等方法。

public class ArrayStack {
    //底層是陣列,建立時要宣告陣列大小
    int[] array;
    int maxSize = 10;
    //維護一個指標訪問棧頂元素,陣列就是下標數字
    int top;

    public ArrayStack() {
        array = new int[maxSize];
        top = -1;
    }

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        array = new int[maxSize];
        top = -1;
    }

    //判斷是否空棧
    public boolean isEmpty() {
        return top == -1;
    }

    //判斷是否滿棧
    public boolean isFull() {
        return top == this.maxSize - 1;
    }

    //入棧
    public void push(int data) {
        if (!isFull()){
            array[++top] = data;
        }
    }

    //出棧,返回棧頂元素
    public int pop() {
        if (!isEmpty()) {
            return array[top--];
        }
        return 0;
    }

    //檢視棧頂元素
    public int peek() {
        return array[top];
    }
}

測試一下:

public class StackTest {
    @Test
    public void testArrayStack() {
        ArrayStack stack = new ArrayStack(10);

        //入棧
        stack.push(14);
        stack.push(23);
        stack.push(65);
        stack.push(12);

        //出棧
        System.out.println("出棧元素:  "+ stack.pop());
        System.out.println("出棧元素:  "+ stack.pop());

        //檢視棧頂元素
        System.out.println("棧頂元素:  "+ stack.peek());
    }
}

執行結果:

出棧元素:  12
出棧元素:  65
棧頂元素:  23

push()入棧方法中將top值加一,指向原來資料項頂端上面的一個位置,並在這位置上儲存一個數據項。
pop()出棧方法返回top標識的資料項,然後再減一。儘管資料項仍在陣列中,但是不能訪問了,直到新元素壓入棧中覆蓋這個資料項
peek()就是訪問top指向的資料項,不修改棧。

3.棧的效率

入棧和出棧時間複雜度O(1);

二、佇列

1.概述

佇列也是一種資料結構,和棧類似,不過佇列中的第一個插入的元素會最先被移除。
佇列的常見操作時建立和入隊、出隊、檢視隊首方法。

public class ArrayQueue {
    //陣列實現佇列,需要宣告大小
    int maxSize = 10;
    int[] array;
    //宣告隊頭指標
    int front;
    //宣告隊尾指標
    int near;
    //記錄元素個數
    int num;

    public ArrayQueue() {
        array = new int[maxSize];
        front = 0;
        near = -1;
        num = 0;
    }

    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        array = new int[maxSize];
        front = 0;
        near = -1;
        num = 0;
    }

    //判斷非空
    public boolean isEmpty() {
        return num == 0;
    }

    //判斷是否滿
    public boolean isFull() {
        return num == maxSize;
    }

    //入隊
    public void insert(int data) {
        if (!isFull()) {
            if (near == maxSize - 1) {      //迴圈佇列
                near = -1;
            }
            array[++near] = data;
            num++;
        }
    }

    //出隊
    public int remove() {
        if (isEmpty()) {
            return -1;
        }
        int temp = array[front];
        if (front == maxSize -1) {
            front = -1;
        }
        front++;
        num--;
        return temp;
    }

    //檢視隊首元素
    public int peekFront() {
        return array[front];
    }

    //佇列資料項數量
    public int size() {
        return  num;
    }
}

測試程式碼:

public class QueueTest {

    @Test
    public void testArrayQueue() {
        ArrayQueue arrayQueue = new ArrayQueue();

        //測試入隊方法
        arrayQueue.insert(23);
        arrayQueue.insert(230);
        arrayQueue.insert(2300);
        arrayQueue.insert(23000);

        //檢視隊首元素
        System.out.println("隊首元素: "+arrayQueue.peekFront());;

        //測試出隊方法
        System.out.println("出隊元素: "+arrayQueue.remove());
        System.out.println("隊首元素: "+arrayQueue.peekFront());;
        System.out.println("出隊元素: "+arrayQueue.remove());
        System.out.println("隊首元素: "+arrayQueue.peekFront());;
        System.out.println("元素個數:" +arrayQueue.size());
    }
}

執行結果:

隊首元素: 23
出隊元素: 23
隊首元素: 230
出隊元素: 230
隊首元素: 2300
元素個數:2
2.佇列的效率

佇列效率和棧一樣,入隊和出隊時間複雜度都是O(1);

3.優先順序佇列

優先順序和佇列和普通佇列一樣,也是有隊首和隊尾,不過優先順序佇列資料項按照關鍵字的值有序。

public class PriorityQueue {
    //陣列實現佇列,需要宣告大小
    int maxSize = 10;
    int[] array;
    //記錄元素個數
    int num;

    public PriorityQueue() {
        array = new int[maxSize];
        num = 0;
    }

    public PriorityQueue(int maxSize) {
        this.maxSize = maxSize;
        array = new int[maxSize];
        num = 0;
    }

    //判斷非空
    public boolean isEmpty() {
        return num == 0;
    }

    //判斷是否滿
    public boolean isFull() {
        return num == maxSize;
    }

    //入隊
    public boolean insert(int data) {
        if (isFull()) {
            return false;
        }
        if (isEmpty()) {
            array[num++] = data;
            return true;
        } else {
            int i;
            for ( i = num - 1; i >= 0; i --) {
                if (array[i] < data) {
                    array[i+1] = array[i];
                } else {
                    break;
                }
            }
            array[i+1] = data;
            num++;
            return true;
        }
    }

    //出隊
    public int remove() {
        if (isEmpty()) {
            return -1;
        } else {
            return array[--num];
        }
    }

    //檢視優先順序最小的元素
    public int peekMin() {
        return array[num-1];
    }

    //佇列資料項數量
    public int size() {
        return  num;
    }

}

測試程式碼:

 @Test
    public void testPriorityQueue() {
        PriorityQueue priorityQueue = new PriorityQueue();

        //入隊
        priorityQueue.insert(78);
        priorityQueue.insert(32);
        priorityQueue.insert(2);
        priorityQueue.insert(788);
        System.out.println("元素個數:" + priorityQueue.size());

        //出隊
        System.out.println("出隊元素: "+ priorityQueue.remove());
        System.out.println("優先順序最小的元素: "+ priorityQueue.peekMin());
        System.out.println("出隊元素: "+ priorityQueue.remove());
        System.out.println("優先順序最小的元素: "+ priorityQueue.peekMin());
        System.out.println("元素個數:" + priorityQueue.size());


        //檢視隊尾元素
        System.out.println("優先順序最小的元素: "+ priorityQueue.peekMin());
    }

執行結果:

元素個數:4
出隊元素: 2
優先順序最小的元素: 32
出隊元素: 32
優先順序最小的元素: 78
元素個數:2
優先順序最小的元素: 78

優先順序佇列的效率:插入的時間複雜度是O(n),刪除的效率是O(1)