栈结构和队列是比较常见的
受限的
线性结构
栈(Stack)
栈的特性
- 限定仅仅在表尾进行插入和删除的操作的线性表,这一端称为栈顶。相对的另一端称之为栈底。
- 原则:后进先出原则
相关名词
- 进栈(push):压入
- 出栈(pop):弹出
生活中的栈
盘子就是一个例子,最先放进去的盘子最后拿走,最后放进去的盘子先拿走。
栈的实现
栈的常见操作
- push 压入元素到栈顶
- pop 弹出栈顶元素
- peek 返回栈顶的元素
- isEmpty 判断栈是否为空
- size 返回栈的元素个数
- toString 栈结构内容以字符串的形式返回
常见的实现方式有
- 基于数组的实现
- 基于链表的实现
此处我们用JS实现栈基于数组的封装作为演示:
//基于数组实现的栈结构
function Stack() {
//存放元素
this.items = []
//将内容压入栈顶
this.__proto__.push = function (value) {
this.items.push(value)
}
//弹出栈顶的元素
this.__proto__.pop = function () {
return this.items.pop()
}
//返回栈的长度
this.__proto__.size = function () {
return this.items.length-1
}
//判断栈是否为空
this.__proto__.isEmpty = function () {
if (this.items.length>0) return false
return true
}
//返回栈顶的元素
this.__proto__.peek = function () {
return this.items[this.items.length-1]
}
//将栈中的内容以字符串的形式输出
this.__proto__.toString = function () {
return this.items.toString()
}
}
var stack = new Stack()
console.log("判断栈是否为空:",stack.isEmpty());
stack.push("张三")
stack.push("李四")
stack.push("王五")
console.log("判断栈是否为空:",stack.isEmpty());
console.log("返回栈顶的元素:",stack.peek())
console.log("将栈中的内容转换城字符串:",stack.toString());
console.log("弹出栈顶元素:",stack.pop())
console.log("将栈中的内容转换城字符串:",stack.toString());
运行结果:
栈的应用
- 十进制数字转换成二进制
function decToBin(dec) {
let decNumber = dec
let stack = new Stack()
let binString = ""
while(decNumber>=1){
stack.push(decNumber%2)
decNumber = Math.floor(decNumber/2)
}
while (!stack.isEmpty()){
binString += stack.pop()
}
return binString
}
console.log(decToBin(63))
运行结果:
队列(Queue)
队列的特性
- 限定仅在表的前端进行删除,在表的后端进行插入操作,和栈 一样是一种操作受限的线性表。
- 原则:先进先出原则
生活中的队列
安检的传送带就是队列的例子,先放进的行李会先完成安检
队列的实现
队列的常见操作
- enQueue 在队列的末尾添加新的一项
- deQueue 在队列的头部移出第一项
- font 返回队列的第一项元素
- isEmpty 判断队列是否为空
- size 返回队列的元素个数
- toString 将队列结构中的内容以字符串的形式返回
常见的实现方式有
- 基于数组的实现
- 基于链表的实现
对于队列用链表的实现方式会比较高效,因为对于数组而言,移出数组中的第一个元素后面的元素都需要往前进行移动。链表对于这种操作是比较快捷的不需要进行移动。
此处先用数组的形式进行实现队列,后续将对其进行补充。
//基于数组实现的队列结构
function Queue() {
//存放元素
this.items = []
//在队列尾部添加新的项
this.__proto__.enQueue = function (value) {
this.items.push(value)
}
//移出队列的第一项
this.__proto__.deQueue = function () {
return this.items.shift()
}
//返回队列的长度
this.__proto__.size = function () {
return this.items.length-1
}
//判断队列是否为空
this.__proto__.isEmpty = function () {
if (this.items.length>0) return false
return true
}
//返回队列的第一项
this.__proto__.font = function () {
return this.items[0]
}
//将队列的内容以字符串的形式输出
this.__proto__.toString = function () {
return this.items.toString()
}
}
var queue = new Queue()
console.log("判断队列是否为空:",queue.isEmpty());
queue.enQueue("张三")
queue.enQueue("李四")
queue.enQueue("王五")
console.log("判断队列是否为空:",queue.isEmpty());
console.log("返回队列的第一项:",queue.font())
console.log("将队列的内容转换城字符串:",queue.toString());
console.log("移出队列的第一项:",queue.deQueue())
console.log("将队列的内容转换城字符串:",queue.toString());
运行结果:
队列的应用
使用队列结构模拟叫号系统的实现
//模拟叫号系统
function callingSystem(arr) {
let queue = new Queue()
arr.forEach((item,index,array ) => {
queue.enQueue(item)
}
)
console.log("叫号队列:",queue.toString())
let flag = setInterval( ()=> {
if (queue.size() == 0){
clearInterval(flag)
}
let name = queue.deQueue()
if (!isCallingSuccess()){
queue.enQueue(name)
console.log(name,"过号重排")
}else {
console.log(name,"叫号成功")
}
console.log("叫号队列:",queue.toString())
},3000)
}
callingSystem(["张三","李四","王五","赵六"])
运行结果: