TypeScript数据结构与算法(4)最基础的数据结构-循环队列-LoopQueue

在上一篇中,实现的是一个数组队列,但是数组队列的时间复杂度高,在本篇实现了一个循环队列LoopQueue,以下是源码:

/**
* Autor: Created by 李清风 on 2020-12-17.
* Desc: 数组循环队列(列表),用来提高效率,降低出队、入队的时间复杂度到O(1),关键词:在不移动内部元素的情况下,通过更改front的指向新的队首元素,来降低时间复杂度,front(用来标记队首)tail用来标记队尾,使用%来求余数
*/
export class DataStruct_LoopQueue<T> implements Interface_Queue<T>{

    private data: T[];
    private front: number;//头元素
    private tail: number; //标记下一个新元素入队时,应该存储的位置
    private size: number;

    public constructor(capacity: number) {
        this.data = new Array<T>(capacity + 1); //循环队列,需要有意识的浪费一个单位
        this.front = this.tail = this.size = 0;
    }

    //获取队列容量大小
    public getCapacity(): number {
        return this.data.length - 1;//减去有意识浪费的那个单位空间
    }

    //获取队列中实际存储的元素个数
    getSize(): number {
        return this.size;
    }

    //判断队列是否为空队列
    isEmpty(): boolean {
        return this.front == this.tail;
    }

    //入队操作
    public enqueue(e: T): void {
        if ((this.tail + 1) % this.data.length == this.front) {
            this.resize(this.getCapacity() * 2);
        }
        this.data[this.tail] = e; //了解入队操作的本质,就是往队尾添加元素
        this.tail = (this.tail + 1) % this.data.length;//设置新的队尾
        this.size++;//每次添加新的元素,都要维护下size
    }

    //出队操作,时间复杂度O1
    public dequeue(): T {
        if (this.isEmpty()) {
            throw new Error("DataStruct_LoopQueue is Empty!");
        }
        let ret: T = this.data[this.front];//出队操作本质,就是从队首拿出元素
        this.data[this.front] = null;
        this.front = (this.front + 1) % this.data.length;//设置新的front元素是谁
        this.size--;

        if (this.size == this.getCapacity() / 4 && this.getCapacity() / 2 != 0) {
            this.resize(this.getCapacity() / 2);
        }
        return ret;
    }

    //调整队列容量
    private resize(expandCount: number) {
        let newData: T[] = new Array<T>(expandCount + 1);
        for (let i = 0; i < this.size; i++) {
            let index = (this.front + i) % this.data.length;
            newData[i] = this.data[index]
        }
        this.data = newData;
        this.front = 0;
        this.tail = this.size;
    }

    //获取队首元素
    public getFront(): T {
        if (this.isEmpty()) {
            throw new Error("DataStruct_LoopQueue is Empty!");
        }
        return this.data[this.front];
    }

}

 实现循环队列LoopQueue时,需要的外部知识:求余数的定义,图我放在下面:

posted @ 2021-01-21 15:33  CYNLINQ  阅读(220)  评论(0)    收藏  举报