问题:链表和数组,哪个队列更快?
分析:
- 队列是先进后出
- 数组是连续存储的,push很快,shift 很慢
- 链表是非连续存储,add 和 delete 都很快
- 结论:链表实现队列更快
链表实现队列
- 单向链表,要同时记录 head 和 tail
- 要从tail 入队,从head 出队
- length要实时记录,不可遍历链表获取
代码实现:
/*** @description 链表实现队列* @author ykk*/ interface ILinkListNode {value: numbernext: ILinkListNode | null } export class QueueWithLink {private head:ILinkListNode | null = nullprivate tail:ILinkListNode | null = nullprivate len: number = 0/*** 入队*/add(n:number){const newNode:ILinkListNode = {value: n,next: null}//处理 headif(this.head == null){this.head = newNode}//处理 tailconst tailNode = this.tail if(tailNode){tailNode.next = newNode}this.tail = newNodethis.len++}/*** 出队,在 head位置*/delete():number | null{if(this.head == null || this.len === 0){return null}//取值const value = this.head.value//修改头节点,指向下一个this.head = this.head.next// 记录长度this.len--return value}get length(): number{return this.len} }
测试用例:
/*** @description 链表实现队列* @author ykk*/ import {QueueWithLink} from './queue-with-list' describe('链表实现队列测试', () =>{it('add delete',()=>{const q = new QueueWithLink()expect(q.length).toBe(0)q.add(100)q.add(200)q.add(300)expect(q.length).toBe(3)})it('length',()=>{const q = new QueueWithLink()expect(q.delete()).toBeNull()q.add(100)q.add(200)q.add(300)expect(q.delete()).toBe(100)expect(q.delete()).toBe(200)}) })
性能测试:
数组实现队列 和 链表实现队列 删除元素的性能测试,代码如下
//性能测试: const p1 = new QueueWithLink() for(let i = 0; i < 10 * 10000; i++){p1.add(i) } console.time('p1') for(let i = 0; i < 10 * 10000; i++){p1.delete() } console.timeEnd('p1')const q2 = [] for(let i = 0; i < 10 * 10000; i++){q2.push(i) } console.time('q2') for(let i = 0; i < 10 * 10000; i++){q2.shift() } console.timeEnd('q2')
执行时间对比:
链表删除的时间比 数组删除数据的时间要快5千多ms。 数字shift 执行时间非常慢