1 栈
栈是一种后入先出(LIFO)的线性逻辑存储结构。只允许在栈顶进行进出操作。
1.1 栈基本操作
基本操作包括:入栈(push)/出栈(pop)/获取栈顶元素(peek)。
栈的实现主要有两种: 1. 数组实现,即顺序栈 2. 链表实现,即链式栈
无论是以数组还是以链表实现,入栈、出栈的时间复杂度都是O(1)。
栈的应用比如函数执行/括号匹配/表达式计算/浏览器前进后退。
1.2 设计栈
1.2.1 数组实现栈
class ArrayStack<T> {
items: T[];
constructor() {
this.items = [];
}
/**
* 入栈
* @param item
*/
push(item: T) {
this.items.push(item);
}
/**
* 出栈
* @returns
*/
pop() {
if (this.isEmpty()) throw new Error('栈空');
return this.items.pop();
}
/**
* 获取栈顶元素
* @returns
*/
peek() {
if (this.isEmpty()) throw new Error('栈空');
return this.items[this.items.length - 1];
}
/**
* 判空
* @returns
*/
isEmpty() {
return this.items.length === 0;
}
/**
* 获取栈元素的个数
* @returns
*/
getSize() {
return this.items.length;
}
}
1.2.2 链表实现栈
class LinkStack<T> {
// 栈的长度
size: number;
// 栈顶指针
top: LinkNode<T> | null;
constructor() {
this.size = 0;
this.top = null;
}
/**
* 入栈
* @param item
*/
push(val: T) {
let node = new LinkNode(val);
if (this.top === null) {
// 栈空
this.top = node;
} else {
// 栈非空
node.next = this.top;
this.top = node;
}
this.size = this.size + 1;
}
/**
* 出栈
* @returns
*/
pop() {
if (this.top === null) {
// 栈空
throw new Error('栈空');
} else {
// 栈非空
const data = this.top.val; // 栈顶元素值
this.top = this.top.next; // 新栈顶
this.size = this.size - 1;
return data;
}
}
/**
* 获取栈顶元素
* @returns
*/
peek() {
if (this.top === null) {
// 栈空
throw new Error('栈空');
} else {
return this.top.val;
}
}
/**
* 判空
* @returns
*/
isEmpty() {
return this.top === null;
}
/**
* 获取栈元素的个数
* @returns
*/
getSize() {
return this.size;
}
}
1.3 剑指 offer 栈算法题( typescript 版)
包含min函数的栈
栈的压入、弹出序列
2 队列
队列是一种先入先出(FIFO)的线性逻辑存储结构。只允许在队首进行出队(即delete删除)操作,队尾进行入队(即insert插入)操作。
2.1 队列基本操作
队列的基本操作包括:入队 (enqueue)/ 出队 (dequeue)/ 获取队头元素(peek)
队列的实现主要有两种: 1. 数组实现,即顺序队列 2. 链表实现,即链式队列。
无论是以数组还是以链表实现,入队、出队的时间复杂度都是O(1)。
队列的应用比如线程池、资源池、消息队列、异步队列。
2.2 设计队列
2.2.1 数组顺序队列
使用数组实现,使用shift出队时每次都要移动队列元素,效率不高。改进方案是可以队列初始化时就需要规定队列长度,通过判断队尾是否有空间,有就让元素一直入队,直到队尾没有空间位置,然后进行整体进行一次搬移,这样优化了入队的效率,平均时间复杂度还是 O(1)。
class ArrayQueue<T> {
items: T[];
constructor() {
this.items = [];
}
/**
* 入队
* @param item
*/
push(item: T) {
this.items.push(item);
}
/**
* 出队
* @returns
*/
pop() {
if (this.isEmpty()) throw new Error('队列空');
return this.items.shift();
}
/**
* 获取队顶元素
* @returns
*/
peek() {
if (this.isEmpty()) throw new Error('队列空');
return this.items[0];
}
/**
* 判空
* @returns
*/
isEmpty() {
return this.items.length === 0;
}
/**
* 获取队元素的个数
* @returns
*/
getSize() {
return this.items.length;
}
}
2.2.2 数组循环队列
数组实现,初始化需指定队列容量capacity,留一个空位,队空条件 head = tail,队满条件 head =( tail + 1) % capacity,队列元素个数(tail - head + capacity) % capacity)。
class LoopQueue {
// 存放元素的数组
values: (number | undefined)[];
// 当前元素个数
count: number;
// 队的长度
capacity: number;
// 队尾
head: number;
// 队尾
tail: number;
constructor(capacity: number) {
this.head = 0;
this.tail = 0;
this.capacity = capacity;
this.count = 0;
this.values = new Array(capacity);
}
/**
* 入队
* @param item
*/
enQueue(val: number) {
if (this.isFull()) {
throw new Error('队满');
}
this.values[this.tail] = val;
this.tail = (this.tail + 1) % this.capacity;
this.count = this.count + 1;
return true;
}
/**
* 出队
* @returns
*/
deQueue(): number {
if (this.isEmpty()) {
throw new Error('队空');
}
const value = this.values[this.head] as number;
this.values[this.head] = undefined;
this.head = (this.head + 1) % this.capacity;
this.count = this.count - 1;
return value;
}
/**
* 获取队头元素
* @returns
*/
peek() {
if (this.isEmpty()) {
throw new Error('队空');
}
const value = this.values[this.head];
return value;
}
/**
* 判空
* @returns
*/
isEmpty() {
// 或 return this.head === this.tail
return this.count === 0;
}
/**
* 判满
* @returns
*/
isFull() {
// 或 return this.head === (this.tail + 1) % this.capacity
return this.count === this.capacity - 1;
}
/**
* 获取队元素的个数
* @returns
*/
getSize() {
return this.count;
}
/**
* 清空队列
* @returns
*/
clear() {
this.head = 0;
this.tail = 0;
this.count = 0;
this.values = new Array(this.capacity);
return true;
}
}
2.2.3 链式顺序队列
链表实现,链表尾入队,链表头出队
class LinkQueue<T> {
// 队的长度
size: number;
// 队尾指针
head: LinkNode<T> | null;
// 队尾指针
tail: LinkNode<T> | null;
constructor() {
this.size = 0;
this.head = null;
this.tail = null;
}
/**
* 入队
* @param item
*/
enQueue(val: T) {
let node = new LinkNode(val);
if (this.size === 0) {
this.head = node;
this.tail = node;
} else {
this.tail!.next = node;
this.tail = this.tail!.next;
}
this.size = this.size + 1;
}
/**
* 出队
* @returns
*/
deQueue() {
if (this.size === 0) {
// 队空
throw new Error('队空');
} else {
// 队非空
const node = this.head;
this.head = node!.next;
this.size = this.size - 1;
return node!.val;
}
}
/**
* 获取队头元素
* @returns
*/
peek() {
if (this.size === 0) {
// 队空
throw new Error('队空');
} else {
return this.head!.val;
}
}
/**
* 判空
* @returns
*/
isEmpty() {
return this.size === 0;
}
/**
* 获取队元素的个数
* @returns
*/
getSize() {
return this.size;
}
}
2.3 剑指 offer 队列算法题( typescript 版)
两个栈实现队列