- vừa được xem lúc

Quick and Dirty Stack, Queue and Deque in JavaScript

0 0 27

Người đăng: Huy Tran

Theo The Full Snack

Quick and Dirty Stack, Queue and Deque in JavaScript

Trong quá trình phỏng vấn, dùng JavaScript, nếu đề bài không yêu cầu bắt buộc phải implement Stack hoặc Queue thì chúng ta có thể tiết kiệm thời gian bằng cách sử dụng Array.

Sở dĩ tiêu đề nói Quick and Dirty là vì cách làm này có thể không bảo đảm đúng hoàn toàn về time complexity, nhưng bù lại nó đúng về mặt concept và behavior của các kiểu dữ liệu, giúp tiết kiệm thời gian khi làm bài phỏng vấn (nhưng đồng thời bạn cũng phải nói rõ vấn đề này với người phỏng vấn, nếu không thì ăn hành ngay).

Việc khai báo Array trong JavaScript khá đơn giản:

// Khai báo mảng rỗng
let array = [];
// Hoặc khai báo mảng n phần tử, fill nó bằng các giá trị 0
let array = Array.from(Array(n)).map(x => 0);

Trong JavaScript thì Array cũng được hỗ trợ một số thao tác, mà ta sẽ dùng nó để mô phỏng lại các kiểu dữ liệu đã đề cập, đó là:

  • push: thêm một phần tử vào cuối array
  • pop: lấy ra phần tử cuối cùng của array
  • unshift: thêm một phần tử vào đầu array
  • shift: lấy ra phần tử đầu tiên của array

Từ đây, ta có thể mô phỏng lại behavior của các kiểu dữ liệu thường gặp.

Mô phỏng Stack

Hai thao tác chính trên stack đó là pushpop, hai hàm này có sẵn trong Array của JavaScript:

let stack = [];
stack.push(5);
stack.pop();

Một thao tác cũng thường gặp trong các implementation của stack đó là peek, giúp xem trước giá trị nằm trên cùng của stack mà không cần lấy nó ra, ta có thể thực hiện việc này bằng cách truy cập trực tiếp dùng index:

let last = stack[stack.length - 1];

Mô phỏng Queue

Hai thao tác thường gặp của queue là enqueue (thêm một phần tử vào queue), và dequeue (lấy một phần tử ra khỏi queue), ta có thể thực hiện việc này bằng hai cách:

let queue = [];
// Enqueue
queue.unshift(5);
// Dequeue
queue.pop();

Hoặc:

let queue = [];
// Enqueue
queue.push(5);
// Dequeue
queue.shift();

Và bạn có thể thấy hai cách trên cũng thể hiện hai hướng hoạt động của một queue (từ trái qua phải, và từ phải qua trái), và nếu gộp chung cả hai cách thì nó cũng chính là một deque (double-ended queue).

Thao tác peek cũng tương tự như với stack, đặc biệt nếu là deque, thì ta sẽ có peek_first (để xem phần tử đầu), và peek_last (để xem phần tử cuối):

let first = queue[0];
let last = queue[queue.length - 1];

Độ phức tạp

Như đã nói ở đầu bài, mình không chắc về độ phức tạp của các thao tác trên nếu dùng Array, nhưng chắc chắn nó sẽ không đúng với độ phức tạp của các thao tác của stack và queue.

Ví dụ như hàm shift, trên queue nó chỉ là O(1), tuy nhiên với JavaScript thì có lẽ nó sẽ chậm hơn rất nhiều.

Để hiểu rõ thêm cách mà JavaScript implement các hàm trên, bạn có thể xem qua đặc tả ECMAScript:

Ứng dụng

Bây giờ mình sẽ thử một bài đơn giản, là implement thuật toán BFS (breadth-first search) và DFS (depth-first search) để duyệt một cây nhị phân, bằng cách sử dụng Array để mô phỏng stack và queue cho từng trường hợp.

Một node của cây có cấu trúc như này:

function Node(val) { this.val = val; this.left = this.right = null;
}

Chúng ta sử dụng queue để implement thuật toán BFS, sau khi duyệt trả về một mảng các giá trị đã duyệt:

const BFS = (root) => { let queue = [root]; let result = []; while (queue.length) { let node = queue.shift(); if (node.left) queue.push(node.left); if (node.right) queue.push(node.right); result.push(node.val); } return result;
};

Để implement DFS thì ta dùng stack:

const DFS = (root) => { let stack = [root]; let arr = []; while (stack.length) { let node = stack.pop(); if (node.left) stack.push(node.left); if (node.right) stack.push(node.right); arr.push(node.val); } return arr;
};

Giả sử với cây input như sau:

 1 / \ 2 3 / / \ 4 5 6 / 7

Kết quả của hai phép duyệt sẽ là:

BFS(input) = [ 1, 2, 3, 4, 5, 6, 7 ]
DFS(input) = [ 1, 3, 6, 5, 7, 2, 4 ]

Happy Coding ^^

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 528

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 436

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 158

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 149

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 113

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 249