用栈模拟队列:算法题背后的原型链课

一、一个问题,两个维度

"用两个栈模拟队列"是经典面试题。但它的价值不止于算法------当代码写出来的时候,JavaScript 的原型机制已经隐含在其中。

这道题的独特之处在于:算法的实现过程同时也是理解语言特性的最佳入口。


二、两个栈模拟队列的核心思路

栈是 FILO,队列是 FIFO,方向正好相反。但两个栈配合就能解决:一个专门接收新元素(输入栈),另一个专门处理出队(输出栈)。

关键操作是"倒数据"------当输出栈为空时,把输入栈的所有元素依次弹出并压入输出栈。由于栈的后进先出特性,倒一次之后,最早进入输入栈的元素就到了输出栈的栈顶。

javascript 复制代码
const MyQueue = function () {
    this.stack1 = []; // 输入栈
    this.stack2 = []; // 输出栈
};

MyQueue.prototype.push = function (x) {
    this.stack1.push(x);
};

MyQueue.prototype.pop = function () {
    if (this.stack2.length === 0) {
        while (this.stack1.length > 0) {
            this.stack2.push(this.stack1.pop());
        }
    }
    return this.stack2.pop();
};

MyQueue.prototype.peek = function () {
    if (this.stack2.length === 0) {
        while (this.stack1.length > 0) {
            this.stack2.push(this.stack1.pop());
        }
    }
    return this.stack2[this.stack2.length - 1];
};

MyQueue.prototype.empty = function () {
    return this.stack1.length === 0 && this.stack2.length === 0;
};

push 永远是 O(1),pop 和 peek 均摊 O(1)------每个元素最多被倒两次。


三、prototype 在这段代码里做了什么

上面用 function + prototype 而非 class 来写。这不是怀旧,而是故意暴露 JavaScript 面向对象的底层机制。

MyQueue.prototype 是一个对象,存放所有实例共享的方法。通过 new MyQueue() 创建的每个实例,内部通过 __proto__ 链接到 MyQueue.prototype,从而访问这些方法。

这背后是一个三层三角关系:

  • 构造函数 MyQueue 有 prototype 属性,指向原型对象
  • 原型对象有 constructor 属性,指回构造函数
  • 实例有 __proto__ 属性,指向原型对象

ES6 的 class 只是这个三层关系的语法糖------typeof MyQueue 不管用哪种写法都是 "function"。


四、new 操作符的四步流程

new MyQueue() 的执行过程不是魔法,是四步操作:

  1. 创建一个空对象 {}
  2. 将这个对象的 __proto__ 指向构造函数的 prototype
  3. 执行构造函数,this 指向新对象,添加属性
  4. 返回这个对象(除非构造函数显式返回了一个对象)
javascript 复制代码
function myNew(constructor, ...args) {
    const obj = {};
    Object.setPrototypeOf(obj, constructor.prototype);
    const result = constructor.apply(obj, args);
    return result instanceof Object ? result : obj;
}

理解这四步之后,const queue = new MyQueue() 不再是一个黑盒。


五、总结

一道算法题加一个语言特性,二者的交汇点不是巧合:

  1. 用栈模拟队列考察的是数据结构组合思维
  2. prototype 机制是 JavaScript 面向对象的基石
  3. new 操作符 = 创建对象 → 绑定原型 → 初始化 → 返回

当你能从算法实现中看到语言底层的运转时,这两方面的知识就不再是孤立的两本书,而是同一块知识地图的不同区域。

相关推荐
Dxy12393102168 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷8 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
椒哥10 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
kyriewen11 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
OpsEye12 小时前
企业大模型压测,需要重点关注哪些指标?
javascript·ai编程
像我这样帅的人丶你还12 小时前
我html生成的doc文档为何在手机文档显示不了图片?
前端·javascript
栉甜16 小时前
Vue2学习内容(上)
前端·javascript·vue.js·学习
shmily麻瓜小菜鸡18 小时前
TypeScript 知识点补充(第三部分:工程化与高级类型)
前端·javascript·typescript
Hilaku18 小时前
前端的技术判断力是怎么练出来的?
前端·javascript·程序员
miofly19 小时前
GitHub 今日推荐|floorplan:AI 读代码自动画交互式架构地图
javascript·开源·github