• 用 ES6 的 WeakMap 实 现 类

    有 一 种 数 据 类 型 可 以 确 保 属 性 是 私 有 的, 这 就是 WeakMap。 我 们 会 在 后 面 深 入 探 讨 Map 这 种 数 据 结 构, 现 在 只 需 要 知 道 WeakMap 可 以 存 储 键 值 对, 其 中 键 是 对 象, 值 可 以 是 任 意 数 据 类 型。 如 果 用 WeakMap 来 存 储 items 变 量, Stack 类 就 是 这 样 的:

    const items = new WeakMap(); //{1}  
    class Stack {
        constructor() {
            items.set(this, []); //{2} 
        }
        push(element) {
            let s = items.get(this); //{3} 
            s.push(element);
        }
        pop() {
            let s = items.get(this);
            let r = s.pop();
            return r;
        } // 其 他 方 法 
    }

    行{ 1}, 声 明 一 个 WeakMap 类 型 的 变 量 items。

    行{ 2}, 在 constructor 中, 以 this( Stack 类 自 己 的 引 用) 为 键, 把 代 表 栈 的

    行{ 3}, 从 WeakMap 中 取 出 值, 即 以 this 为 键( 行{ 2} 设 置 的) 从 items 中 取 值。

    现 在 我 们 知 道, items 在 Stack 类 里 是 真 正 的 私 有 属 性 了, 但 还 有 一 件 事 要 做。 items 现 在 仍 然 是 在 Stack 类 以 外 声 明 的, 因 此 谁 都 可 以 改 动 它。 我 们 要 用 一 个 闭 包( 外 层 函 数) 把 Stack 类 包 起 来, 这 样 就 只 能 在 这 个 函 数 里 访 问 WeakMap:

    1 let Stack = (function () {
    2     const items = new WeakMap();
    3     class Stack {
    4         constructor() {
    5             items.set(this, []);
    6         } // 其 他 方 法 
    7     }
    8     return Stack; //{5} 
    9 })();

    当 Stack 函 数 里 的 构 造 函 数 被 调 用 时, 会 返 回 Stack 类 的 一 个 实 例( 行{ 5})。

    栈 的 实 际 应 用 非 常 广 泛。 在 回 溯 问 题 中, 它 可 以 存 储 访 问 过 的 任 务 或 路 径、 撤 销 的 操 作( 后 面 的 章 节 讨 论 图 和 回 溯 问 题 时, 我 们 会 学 习 如 何 应 用 这 个 例 子)。 Java 和 C# 用 栈 来 存 储 变 量 和 方 法 调 用, 特 别 是 处 理 递 归 算 法 时, 有 可 能 抛 出 一 个 栈 溢 出 异 常( 后 面 的 章 节 也 会 介 绍)。 既 然 我 们 已 经 了 解 了 Stack 类 的 用 法, 不 妨 用 它 来 解 决 一 些 计 算 机 科 学 问 题。 本 节, 我 们 将 学 习 使 用 栈 的 三 个 最 著 名 的 算 法 示 例。 首 先 是 十 进 制 转 二 进 制 问 题, 以 及 任 意 进 制 转 换 的 算 法; 然 后 是 平 衡 圆 括 号 问 题; 最 后, 我 们 会 学 习 如 何 用 栈 解 决 汉 诺 塔 问 题。

    从 十 进 制 到 二 进 制

    现 实 生 活 中, 我 们 主 要 使 用 十 进 制。 但 在 计 算 科 学 中, 二 进 制 非 常 重 要, 因 为 计 算 机 里 的 所 有 内 容 都 是 用 二 进 制 数 字 表 示 的( 0 和 1)。 没 有 十 进 制 和 二 进 制 相 互 转 化 的 能 力, 与 计 算 机 交 流 就 很 困 难。 要 把 十 进 制 转 化 成 二 进 制, 我 们 可 以 将 该 十 进 制 数 字 和 2 整 除( 二 进 制 是 满 二 进 一), 直 到 结 果 是 0 为 止。 举 个 例 子, 把 十 进 制 的 数 字 10 转 化 成 二 进 制 的 数 字, 过 程 大 概 是 这 样:

     

    大 学 的 计 算 机 课 一 般 都 会 先 教 这 个 进 制 转 换。 下 面 是 对 应 的 算 法 描 述:

     1 function divideBy2(decNumber) {
     2     var remStack = new Stack(),
     3         rem, binaryString = '';
     4     while (decNumber > 0) { //{1} 
     5         rem = Math.floor(decNumber % 2); //{2} 
     6         remStack.push(rem); //{3} 
     7         decNumber = Math.floor(decNumber / 2); //{4} 
     8     }
     9     while (!remStack.isEmpty()) { //{5} 
    10         binaryString += remStack.pop().toString();
    11     }
    12     return binaryString;
    13 }

    在 这 段 代 码 里, 当 结 果 满 足 和 2 做 整 除 的 条 件 时( 行{ 1}), 我 们 会 获 得 当 前 结 果 和 2 的 余 数, 放 到 栈 里( 行{ 2}、{ 3})。 然 后 让 结 果 和 2 做 整 除( 行{ 4})。 另 外 请 注 意: JavaScript 有 数 字 类 型, 但 是 它 不 会 区 分 究 竟 是 整 数 还 是 浮 点 数。 因 此, 要 使 用 Math.floor 函 数 让 除 法 的 操 作 仅 返 回 整 数 部 分。 最 后, 用 pop 方 法 把 栈 中 的 元 素 都 移 除, 把 出 栈 的 元 素 变 成 连 接 成 字 符 串( 行{ 5})。 用 刚 才 写 的 算 法 做 一 些 测 试, 使 用 以 下 代 码 把 结 果 输 出 到 控 制 台 里:

    1 console.log(divideBy2(233));
    2 console.log(divideBy2(10));
    3 console.log(divideBy2(1000));

    进 制 转 换 算 法

    我 们 很 容 易 修 改 之 前 的 算 法, 使 之 能 把 十 进 制 转 换 成 任 何 进 制。 除 了 让 十 进 制 数 字 和 2 整 除 转 成 二 进 制 数, 还 可 以 传 入 其 他 任 意 进 制 的 基 数 为 参 数, 就 像 下 面 算 法 这 样:

     1 function baseConverter(decNumber, base) {
     2     var remStack = new Stack(),
     3         rem, baseString = '',
     4         digits = '0123456789ABCDEF'; //{6} 
     5     while (decNumber > 0) {
     6         rem = Math.floor(decNumber % base);
     7         remStack.push(rem);
     8         decNumber = Math.floor(decNumber / base);
     9     }
    10     while (!remStack.isEmpty()) {
    11         baseString += digits[remStack.pop()]; //{7} 
    12     }
    13     return baseString;
    14 }

    我 们 只 需 要 改 变 一 个 地 方。 在 将 十 进 制 转 成 二 进 制 时, 余 数 是 0 或 1; 在 将 十 进 制 转 成 八 进 制 时, 余 数 是 0 到 7 之 间 的 数; 但 是 将 十 进 制 转 成 16 进 制 时, 余 数 是 0 到 9 之 间 的 数 字 加 上 A、 B、 C、 D、 E 和 F( 对 应 10、 11、 12、 13、 14 和 15)。 因 此, 我 们 需 要 对 栈 中 的 数 字 做 个 转 化 才 可 以( 行{ 6} 和 行{ 7})。

    可 以 使 用 之 前 的 算 法, 输 出 结 果 如 下:

    1 console.log(baseConverter(100345, 2));
    2 console.log(baseConverter(100345, 8));
    3 console.log(baseConverter(100345, 16));

     回文判断

     1 //回文判断
     2 
     3 function isPalindrome ( word ) {
     4     var s = new Stack();
     5     for( var i = 0 ; i < word.length ; i ++ ){
     6         s.push( word[i] );
     7     }
     8     var rword = '';
     9     while( s.length() > 0 ){
    10         rword += s.pop();
    11     }
    12 
    13     if( word == rword ){
    14         return true;
    15     }else{
    16         return false;
    17     }
    18 }
    19 
    20 console.log( isPalindrome('level') )    // true
    21 console.log( isPalindrome('1001') )     // true
    22 console.log( isPalindrome('word') )     // false
  • 相关阅读:
    RPC细谈
    RPC浅谈
    动态规划
    libco 的定时器实现: 时间轮
    一次HTTP请求的完整过程——协议篇(DNS、TCP、HTTP)
    多个CPU、多核CPU以及超线程(Hyper-Threading)
    Linux下which、whereis、locate、find命令的区别
    warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
    使用OutputDebugString输出调试信息
    VS或windows用代码产生GUID
  • 原文地址:https://www.cnblogs.com/xfcao/p/12012614.html
Copyright © 2020-2023  润新知