复习 栈和队列
栈和队列
前言:
我们知道数组是一种线性结构,并且可以在任意位置进行插入和删除,有时候为了实现某些功能,需要对这种任意性加以限制,而栈和队列就是比较常见的受限的线性表结构,
栈
仅允许在表的一端进行插入和删除,这一端称为栈顶,另一端称为栈低。后进先出LIFO(last in first out)
:向一个栈插入元素叫做进栈,压栈,入栈,将新元素放到栈顶元素的上面,成为新的栈顶元素;从栈顶删除元素叫做出栈,退栈,删除栈顶元素,使其相邻的元素成为新的栈顶元素;
基于数组实现
function Stack() {
this.data = [] // 用来存储栈中的数据
// 向栈顶添加一个元素
Stack.prototype.push = ele => {
this.data.push(ele)
}
// 向栈顶删除一个元素,同时返回被移除的元素
Stack.prototype.pop = () => {
return this.data.pop()
}
// 返回栈顶元素
Stack.prototype.peek = () => {
return this.data[this.data.length - 1]
}
// 判断栈是否为空
Stack.prototype.isEmpty = () => {
return this.data.length === 0
}
// 返回栈里面的元素的个数
Stack.prototype.size = () => {
return this.data.length
}
// 将栈结构里面的内容以字符串形式返回
Stack.prototype.toString = () => {
return this.data.join('')
}
}
基于链表实现
// 简易链表
function LinkedList() {
this.head = null
function Node(ele, next = null) {
this.ele = ele
this.next = next
}
this.length = 0
//insert 在position位置前面插入节点
LinkedList.prototype.insert = (position, ele) => {
if (position < 0 || position > this.length) return
const newNode = new Node(ele)
const currentNode = this.head
this.head = newNode
newNode.next = currentNode
this.length += 1
}
// removeAt 删除最前面的节点
LinkedList.prototype.removeAt = () => {
const currentNode = this.head
this.head = currentNode.next
this.length -= 1
return currentNode
}
// 转字符串
LinkedList.prototype.toString = () => {
let currentEle = this.head
let str = ''
while (currentEle) {
str += currentEle.ele + '-'
currentEle = currentEle.next
}
return str
}
// 清空链表
LinkedList.prototype.clear = () => {
this.head = null
this.length = 0
}
}
function Stack() {
this.data = new LinkedList()
// 入栈
Stack.prototype.push = ele => this.data.insert(0, ele)
// 出栈
Stack.prototype.pop = () => this.data.removeAt()
// 转字符串
Stack.prototype.toString = () => this.data.toString()
// 返回栈顶元素
Stack.prototype.peek = () => this.data.head
Stack.prototype.size = () => this.data.length
Stack.prototype.isEmpty = () => this.data.length === 0
Stack.prototype.clear = () => this.data.clear()
}
队列
在表的一端进行插入元素,这一端称为表的后端(rear),在表的另一端删除元素,这一端称为表的前端(front);先进先出 FIFO(first in first out)
基于数组实现
function Queue() {
this.data = []
Queue.prototype.enqueue = (ele) => {
this.data.push(ele)
}
Queue.prototype.dequeue = () => {
return this.data.shift()
}
Queue.prototype.front = () => {
return this.data[0]
}
Queue.prototype.isEmpty = () => {
return this.data.length === 0
}
Queue.prototype.size = () => {
return this.data.length
}
Queue.prototype.toString = () => {
return this.data.join('')
}
}
基于链表实现
// 简易链表
function LinkedList() {
this.head = null
function Node(ele, next = null) {
this.ele = ele
this.next = next
}
this.length = 0
//append 向列表末尾插入节点
LinkedList.prototype.append = ele => {
const newNode = new Node(ele)
if (this.length === 0) {
// 链表为空时直接插入
this.head = newNode
// newNode.next = null
} else {
// 链表不为空的时候插入到最后一个节点后面
let currentNode = this.head
// 遍历链表,找到最后一个节点
while (currentNode.next) {
currentNode = currentNode.next
}
currentNode.next = newNode
newNode.next = null
}
// 让长度加一
this.length += 1
}
// removeAt 删除最前面的节点
LinkedList.prototype.removeAt = () => {
const currentNode = this.head
this.head = currentNode.next
this.length -= 1
return currentNode
}
// 转字符串
LinkedList.prototype.toString = () => {
let currentEle = this.head
let str = ''
while (currentEle) {
str += currentEle.ele + '-'
currentEle = currentEle.next
}
return str
}
// 清空链表
LinkedList.prototype.clear = () => {
this.head = null
this.length = 0
}
}
function Queue() {
this.data = new LinkedList()
// 入队
Queue.prototype.enqueue = ele => this.data.append(ele)
// 出队
Queue.prototype.dequeue = () => this.data.removeAt()
// 转字符串
Queue.prototype.toString = () => this.data.toString()
// 返回队列第一个元素
Queue.prototype.front = () => this.data.head
Queue.prototype.isEmpty = () => this.data.length === 0
Queue.prototype.size = () => this.data.length
Queue.prototype.clear = () => this.data.clear()
}
特殊的队列-----优先级队列
普通的队列插入一个元素会被放在表的后端,并且只有前面的数据处理完成后,才会处理当前数据,比如删除。当是优先级队列在插入元素的时候会考虑它的优先级,让当前元素的优先级与其他元素比较,比较完成后在插入到正确的位置
function PriorityQueue() {
this.data = []
function QueueElement(ele, priority) {
this.element = ele
this.priority = priority
}
// 改造插入方法,不再是普通插入,通过比较优先级之后在进行插入操作
PriorityQueue.prototype.enqueue = (ele, priority) => {
const currentEle = new QueueElement(ele, priority)
// 如果队列为空,直接插入
if (this.isEmpty()) {
this.data.push(currentEle)
} else {
let right = this.size() - 1
while (right >= 0 && currentEle.priority <= this.data[right].priority) {
right--
}
right++
this.data.splice(right, 0, currentEle)
}
}
PriorityQueue.prototype.dequeue = () => {
return this.data.shift()
}
PriorityQueue.prototype.front = () => {
return this.data[0]
}
PriorityQueue.prototype.isEmpty = () => {
return this.data.length === 0
}
PriorityQueue.prototype.size = () => {
return this.data.length
}
PriorityQueue.prototype.toString = () => {
return this.data.join('')
}
}
const priority = new PriorityQueue()
priority.enqueue('p0', 0)
priority.enqueue('p3', 3)
priority.enqueue('p1', 1)
priority.enqueue('p4', 4)
priority.enqueue('p2', 2)
console.log(priority.data)