携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情
双端队列数据结构
双端队列是一种允许同时从顶部和尾部添加和移除元素的特殊队列。
在计算机科学中,双端队列的一个常见应用是存储一系列的撤销操作。当用户在软件中进行了一个操作,该操作会被保存在一个双端队列中。当用户撤销时,该操作会从双端队列中弹出,表示从队尾移除了。当保存了一定数量的操作后,还有操作被保存进来,就会把队顶的操作移除。
所以双端队列同时遵守了先进先出和后进先出的原则,可以说它是队列和栈相结合的一种数据结构。
创建 Deque 类
class Deque {
constructor() {
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
}
因为双端队列是一种特殊的队列,所以它们有相同的内部属性和以下方法:isEmpty、clear、size、toString。
双端队列允许在两端添加和移除元素,所以还有一些新的方法:
addFront(el) {
if (this.isEmpty()) {
this.addBack(el);
} else if (this.lowestCount > 0) {
this.lowerCount--;
this.items[this.lowestCount] = el;
} else {
for (let i = this.count; i > 0; i--) {
this.items[i] = this.items[i - 1];
}
this.count++;
this.lowerCount = 0;
this.items[0] = el;
}
}
将一个元素添加到双端队列的队顶,存在三种场景:
- 双端队列为空时,执行
addBack方法,将元素添加到队尾。 - 如果双端队列的队顶在之前有元素被删除,
lowestCount属性大于等于1时,只需要将lowestCount属性减1并以这个值为键,元素为值插入对象即可。 - 如果
lowestCount属性值为0,需要把双端队列里的值往后顺延一位,将队顶位置空出来,然后用新添加的元素覆盖它即可了。
//addBack(el):该方法在双端队列后端添加新的元素
addBack(el) {
this.items[this.count] = el;
this.count++;
}
//removeFront():该方法会从双端队列前端移除第一个元素
removeFront() {
if (this.isEmpty()) {
return undefined;
}
const result = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount++;
return result;
}
//removeBack():该方法会从双端队列后端移除第一个元素
removeBack() {
if (this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}
//peekFront():该方法返回双端队列前端的第一个元素
peekFront() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.lowestCount];
}
//peekBack():该方法返回双端队列后端的第一个元素
peekBack() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.count - 1];
}
使用 Deque 类
const deque = new Deque
console.log(deque.isEmpty()); //true
deque.addBack("jack");
deque.addFront("jiaji");
console.log(deque.toString());
deque.removeBack();
deque.addFront("john");
console.log(deque.size());
console.log(deque.toString());
回文检查器
回文是正反都能读通的单词、词组、数或一系列字符的序列,例如 madam或 racecar。
检查一个词组或者字符串有很多方法,最简单的方式就是将字符串置反后与原字符串比较,如果相同,就是回文。也可以用数据结构栈来完成,但是用数据结构最简单的方法是用双端队列。
//回文检查器
function palindromeChecker(aString) {
//检查传入的字符串是否合法
if (
aString === undefined ||
aString === null ||
aString.trim().length === 0
) {
return false;
}
//实例化双端队列
const deque = new Deque();
//将字符串转为小写并移除所有空格
const lowerString = aString.toLocaleLowerCase().split(" ").join("");
//默认是回文
let isEqual = true;
//第一个字符,最后一个字符
let firstChar, lastChar;
for (let i = 0; i < lowerString.length; i++) {
//将每个字符添加到双端队列中
deque.addBack(lowerString.charAt(i));
}
//循环双端队列中的每一个元素,如果isEqual为false,表示不是回文
while (deque.size() > 1 && isEqual) {
//移除第一个字符
firstChar = deque.removeFront();
//移除最后一个字符
lastChar = deque.removeBack();
//如果不相等,表示不是回文
if (firstChar !== lastChar) {
isEqual = false;
}
}
return isEqual;
}
console.log('a', palindromeChecker('a'));
console.log('aa', palindromeChecker('aa'));
console.log('kayak', palindromeChecker('jiaij'));
console.log('Was it a car or a cat I saw', palindromeChecker('Was it a car or a cat I saw'));
console.log('Step on no pets', palindromeChecker('Step on no pets'));
\