先赞再看, 养成习惯 :P
俗话说得好, "时刻准备着"。
算法和数据结构, 对工程师来说是十分重要的。
而这一部分, 靠短期的冲刺学习是很难掌握的。只有靠刻意的学习和不断练习才能掌握。
今天我们就来复习下队列。
了解队列的使用姿势
队列是非常常见的数据结构, 面试中也经常出现。
今天我们就说一下这种数据结构, 然后看两道题。
文中可能涉及到链表,链表我在之前的文章中写过,参考链接:
[第28期] 回顾一下常见的链表操作
[第29期] 熟悉链表的几个经典题目
队列
队列是一种线性的数据结构, 表现上是先进先出, FIFO.
生活中典型的场景就是排队了,从后插入新元素, 移除最旧的元素:
下面我们用两种姿势来实现一个队列:
- 栈
- 链表
leetcode #232 用栈实现队列
使用栈实现队列的下列操作:
- push(x) -- 将一个元素放入队列的尾部。
- pop() -- 从队列首部移除元素。
- peek() -- 返回队列首部的元素。
- empty() -- 返回队列是否为空。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
1.用栈实现队列
栈是一种先进后出的数据结构, 队列是一种先进先出的数据结构,那怎么用栈来模拟队列呢?
很简单, 倒两次就行了。
用两个栈, 一个用于入队, 一个用于出队:
图解:
代码实现:
/**
* Initialize your data structure here.
*/
var MyQueue = function() {
this.input = [];
this.output = [];
};
/**
* Push element x to the back of queue.
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
this.input.push(x);
};
/**
* Removes the element from in front of queue and returns that element.
* @return {number} 从队列首部移除元素
*/
MyQueue.prototype.pop = function() {
while (this.input.length) {
this.output.push(this.input.pop());
}
var first = this.output.pop();
while (this.output.length) {
this.input.push(this.output.pop());
}
return first;
};
/**
* Get the front element. 返回队列首部的元素。
* @return {number}
*/
MyQueue.prototype.peek = function() {
return this.input[0];
};
/**
* Returns whether the queue is empty.
* @return {boolean} 返回队列是否为空
*/
MyQueue.prototype.empty = function() {
return !this.input.length && !this.output.length;
};
var obj = new MyQueue();
obj.push(1);
obj.push(2);
obj.push(3);
var param_2 = obj.pop();
console.log(param_2); // 队首出来, 1
var param_3 = obj.peek();
console.log(param_3); // 返回队列首部的元素: 2
var param_4 = obj.empty();
console.log('isEmpty: ', param_4); // false
2. 用链表实现队列
链表我们都很熟悉了, 之前两期都是关于链表的:xxx, xxx
先看一下基础结构, 包含我们要实现哪些功能:
// Queue using linkedlist
function QueueUsingLinkList() {
let Node = function(elm) {
this.element = elm;
this.next = null;
};
// To keep track of the size
let length = 0;
//To keep track of the list
let head = null;
// Enqueue data in the queue
this.enqueue = function(elm) {};
// Remove the item from the queue
this.dequeue = function() {};
// Return the first element in the queue
this.peek = function() {};
//Return the last element in the queue
this.rear = function() {};
//Check if queue is empty
this.isEmpty = function() {};
//Return the size of the queue
this.size = function() {};
//Clear the queue
this.clear = function() {};
}
enqueue, 往队列中添加元素
首先要检查队列是不是空的, 如果是空的, 就把新元素当成头结点,否则, 就把新元素加到末尾。
代码实现:
//Enqueue data in the queue
this.enqueue = function (elm) {
let node = new Node(elm),
current;
//If head is empty then
//Add the node at the beginning
if (head === null) {
head = node;
} else {
//Else add the node as the
//Next element of the existing list
current = head;
while (current.next) {
current = current.next;
}
current.next = node;
}
//Increase the length
length++;
};
dequeue, 从队列中删除元素
队列是先进先出的数据结构, 所以出队的时候, 要移除并返回头部的元素,长度减一,并把指针往后移步一位。
代码实现:
//Remove the item from the queue
this.dequeue = function () {
let current = head;
//If there is item then remove it
//and make the next element as the first
if (current) {
let elm = current.element;
current = current.next;
head = current;
length--;
return elm;
}
return null;
}
其他辅助方法
核心的入队, 出队,我们已经实现了, 为了方便调试, 我们顺便实现几个辅助函数:
- peek 查看头部元素
- rear 查看尾部元素
- to array 转换成数组
- size 查看大小
- isEmpty 查看是否为空
- 清空队列
isEmpty
//Check if queue is empty
this.isEmpty = function() {
return length === 0;
}
size
//Return the size of the queue
this.size = function() {
return length;
}
以数组的形势查看:
//Convert the queue to an array
this.toArray = function () {
let arr = [];
let current = head;
while (current) {
arr.push(current.element);
current = current.next;
}
return arr;
}
rear 查看尾部元素
//Return the last element in the queue
this.rear = function () {
let current = head;
//If head is empty
//Return null
if (current === null) {
return null;
}
//Return the last elememnt
while (current.next) {
current = current.next;
}
return current.element;
}
peek
//Return the first element in the queue
this.peek = function () {
if (head) {
return head.element;
}
return null;
}
clear
//Clear the queue
this.clear = function() {
head = null;
length = 0;
}
测试
let queue = new QueueUsingLinkList();
console.log(queue.isEmpty()); // true
queue.enqueue('pranav');
queue.enqueue('sachin');
queue.enqueue('yogesh');
console.log(queue.toArray()); // ["pranav", "sachin", "yogesh"]
queue.dequeue();
queue.dequeue();
console.log(queue.toArray()); // ["yogesh"]
queue.enqueue('prashant');
queue.enqueue('yadav');
queue.dequeue();
console.log(queue.toArray()); // ["prashant", "yadav"]
console.log(queue.size()); // 2
console.log(queue.peek()); // "prashant"
console.log(queue.rear()); // "yadav"
完整代码
//Queue using linkedlist
function QueueUsingLinkList() {
//Node
let Node = function (elm) {
this.element = elm;
this.next = null;
}
//To keep track of the size
let length = 0;
//To keep track of the list
let head = null;
//Enqueue data in the queue
this.enqueue = function (elm) {
let node = new Node(elm),
current;
//If head is empty then
//Add the node at the beginning
if (head === null) {
head = node;
} else {
//Else add the node as the
//Next element of the existing list
current = head;
while (current.next) {
current = current.next;
}
current.next = node;
}
//Increase the length
length++;
}
//Remove the item from the queue
this.dequeue = function () {
let current = head;
//If there is item then remove it
//and make the next element as the first
if (current) {
let elm = current.element;
current = current.next;
head = current;
length--;
return elm;
}
return null;
}
//Return the first element in the queue
this.peek = function () {
if (head) {
return head.element;
}
return null;
}
//Return the last element in the queue
this.rear = function () {
let current = head;
//If head is empty
//Return null
if (current === null) {
return null;
}
//Return the last elememnt
while (current.next) {
current = current.next;
}
return current.element;
}
//Convert the queue to an array
this.toArray = function () {
let arr = [];
let current = head;
while (current) {
arr.push(current.element);
current = current.next;
}
return arr;
}
//Check if queue is empty
this.isEmpty = function () {
return length === 0;
}
//Return the size of the queue
this.size = function () {
return length;
}
//Clear the queue
this.clear = function () {
head = null;
length = 0;
}
}
总结
掌握这些常见的数据结的基础操作,对我们的日常工作也有好处。
要学好数据结构和算法, 需要 三分理论, 七分实践。
希望今天的内容对你有所启发,谢谢 :)
最后
如果你觉得内容有帮助, 可以关注下我的公众号 「 前端e进阶 」,一起学习, :)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。