# 链表实现队列
# 栈结构
# 定义
- 允许插入和删除的一端称为栈顶,另一端称为栈底
- 不含任何数据元素的栈称为空栈
- 后进先出的数据结构
# 代码实现
class Stack{
constructor() {
this.stack = []
}
put(element){ //进栈
this.stack.push(element)
}
pop() { //出栈
this.stack.pop()
}
}
//调用
let stack = new Stack()
stack.put(1)
stack.put(2)
stack.pop()
console.log(stack.stack)
# 单向链表
# 定义
- 链表中的元素不是连续放置的
- 每个元素由一个存储元素本身的节点和指向下一个元素的引用组成
- 添加或移动元素的时候不需要移动其它元素
# 用列表实现队列
/**
* @description 用链表实现队列
* @author
*/
interface IListNode {
value: number
next: IListNode | null
}
export class MyQueue {
private head: IListNode | null = null
private tail: IListNode | null = null
private len = 0
/**
* 入队,在 tail 位置
* @param n number
*/
add(n: number) {
const newNode: IListNode = {
value: n,
next: null,
}
// 处理 head
if (this.head == null) {
this.head = newNode
}
// 处理 tail
const tailNode = this.tail
if (tailNode) {
tailNode.next = newNode
}
this.tail = newNode
// 记录长度
this.len++
}
/**
* 出队,在 head 位置
*/
delete(): number | null {
const headNode = this.head
if (headNode == null) return null
if (this.len <= 0) return null
// 取值
const value = headNode.value
// 处理 head
this.head = headNode.next
// 记录长度
this.len--
return value
}
get length(): number {
// length 要单独存储,不能遍历链表来获取(否则时间复杂度太高 O(n))
return this.len
}
}
// // 功能测试
// const q = new MyQueue()
// q.add(100)
// q.add(200)
// q.add(300)
// console.info('length1', q.length)
// console.log(q.delete())
// console.info('length2', q.length)
// console.log(q.delete())
// console.info('length3', q.length)
// console.log(q.delete())
// console.info('length4', q.length)
// console.log(q.delete())
// console.info('length5', q.length)
// // 性能测试
// const q1 = new MyQueue()
// console.time('queue with list')
// for (let i = 0; i < 10 * 10000; i++) {
// q1.add(i)
// }
// for (let i = 0; i < 10 * 10000; i++) {
// q1.delete()
// }
// console.timeEnd('queue with list') // 17ms
// const q2 = []
// console.time('queue with array')
// for (let i = 0; i < 10 * 10000; i++) {
// q2.push(i) // 入队
// }
// for (let i = 0; i < 10 * 10000; i++) {
// q2.shift() // 出队
// }
// console.timeEnd('queue with array') // 431ms
# 单元测试
import { MyQueue } from './queue-with-list'
describe('链表实现队列', () => {
it('add and length', () => {
const q = new MyQueue()
expect(q.length).toBe(0)
q.add(100)
q.add(200)
q.add(300)
expect(q.length).toBe(3)
})
it('delete', () => {
const q = new MyQueue()
expect(q.delete()).toBeNull()
q.add(100)
q.add(200)
q.add(300)
expect(q.delete()).toBe(100)
expect(q.delete()).toBe(200)
expect(q.delete()).toBe(300)
expect(q.delete()).toBeNull()
})
})
# 实际开发中
在实际开发中,如果我们队数据结构的要求不是特别高,一般会采用一个无限制的数组模拟队列,使用数组的push方法和shift方法来实现出栈和入栈,通过判断数组的长度来判断其是否为空。比较简便。
export class Queue {
constructor() {
this._arr = [];
}
toString(){
return this._arr.toString();
}
// 入队
push(data){
return this._arr.push(data);
}
// 出队
pop(){
return this._arr.shift();
}
// 获取队头
head(){
return this._arr.length ? this._arr[0] : null;
}
// 获取队尾
rear(){
return this._arr.length ? this._arr[this._arr.length-1] : null;
}
// 判断是否为空
isEmpty(){
return !!this._arr.length;
}
}