资讯专栏INFORMATION COLUMN

JS之数据结构与算法 (5)

wangtdgoodluck / 423人阅读

摘要:序列文章面试之函数面试之对象面试之数组的几个不操作面试之对比分析前言数据结构是计算机存储组织数据的方式算法是系统描述解决问题的策略。了解基本的数据结构和算法可以提高代码的性能和质量。

序列文章

JS面试之函数(1)
JS面试之对象(2)
JS面试之数组的几个不low操作(3)
JS面试之http0.9~3.0对比分析(4)

前言
数据结构是计算机存储、组织数据的方式,算法是系统描述解决问题的策略。了解基本的数据结构和算法可以提高代码的性能和质量。
也是程序猿进阶的一个重要技能。
手撸代码实现栈,队列,链表,字典,二叉树,动态规划和贪心算法
1.数据结构篇 1.1 栈

栈的特点:先进后出

class Stack {
    constructor() {
      this.items = [];
    }

    // 入栈
    push(element) {
      this.items.push(element);
    }

    // 出栈
    pop() {
      return this.items.pop();
    }

    // 末位
    get peek() {
      return this.items[this.items.length - 1];
    }

    // 是否为空栈
    get isEmpty() {
      return !this.items.length;
    }

    // 长度
    get size() {
      return this.items.length;
    }

    // 清空栈
    clear() {
      this.items = [];
    }
  }

  // 实例化一个栈
  const stack = new Stack();
  console.log(stack.isEmpty); // true

  // 添加元素
  stack.push(5);
  stack.push(8);

  // 读取属性再添加
  console.log(stack.peek); // 8
  stack.push(11);
  console.log(stack.size); // 3
  console.log(stack.isEmpty); // false
1.2 队列

队列:先进先出

  class Queue {
    constructor(items) {
      this.items = items || [];
    }

    enqueue(element) {
      this.items.push(element);
    }

    dequeue() {
      return this.items.shift();
    }

    front() {
      return this.items[0];
    }

    clear() {
      this.items = [];
    }

    get size() {
      return this.items.length;
    }

    get isEmpty() {
      return !this.items.length;
    }

    print() {
      console.log(this.items.toString());
    }
  }

  const queue = new Queue();
  console.log(queue.isEmpty); // true

  queue.enqueue("John");
  queue.enqueue("Jack");
  queue.enqueue("Camila");
  console.log(queue.size); // 3
  console.log(queue.isEmpty); // false
  queue.dequeue();
  queue.dequeue();
  
1.3 链表

链表:存贮有序元素的集合,
但是不同于数组,每个元素是一个存贮元素本身的节点和指向下一个元素引用组成
要想访问链表中间的元素,需要从起点开始遍历找到所需元素

    
class Node {
    constructor(element) {
      this.element = element;
      this.next = null;
    }
  }

  // 链表
  class LinkedList {
    constructor() {
      this.head = null;
      this.length = 0;
    }

    // 追加元素
    append(element) {
      const node = new Node(element);
      let current = null;
      if (this.head === null) {
        this.head = node;
      } else {
        current = this.head;
        while (current.next) {
          current = current.next;
        }
        current.next = node;
      }
      this.length++;
    }

    // 任意位置插入元素
    insert(position, element) {
      if (position >= 0 && position <= this.length) {
        const node = new Node(element);
        let current = this.head;
        let previous = null;
        let index = 0;
        if (position === 0) {
          this.head = node;
        } else {
          while (index++ < position) {
            previous = current;
            current = current.next;
          }
          node.next = current;
          previous.next = node;
        }
        this.length++;
        return true;
      }
      return false;
    }

    // 移除指定位置元素
    removeAt(position) {
      // 检查越界值
      if (position > -1 && position < length) {
        let current = this.head;
        let previous = null;
        let index = 0;
        if (position === 0) {
          this.head = current.next;
        } else {
          while (index++ < position) {
            previous = current;
            current = current.next;
          }
          previous.next = current.next;
        }
        this.length--;
        return current.element;
      }
      return null;
    }

    // 寻找元素下标
    findIndex(element) {
      let current = this.head;
      let index = -1;
      while (current) {
        if (element === current.element) {
          return index + 1;
        }
        index++;
        current = current.next;
      }
      return -1;
    }

    // 删除指定文档
    remove(element) {
      const index = this.indexOf(element);
      return this.removeAt(index);
    }

    isEmpty() {
      return !this.length;
    }

    size() {
      return this.length;
    }

    // 转为字符串
    toString() {
      let current = this.head;
      let string = "";
      while (current) {
        string += ` ${current.element}`;
        current = current.next;
      }
      return string;
    }
  }
  const linkedList = new LinkedList();

  console.log(linkedList);
  linkedList.append(2);
  linkedList.append(6);
  linkedList.append(24);
  linkedList.append(152);

  linkedList.insert(3, 18);
  console.log(linkedList);
  console.log(linkedList.findIndex(24));  
  
1.4 字典

字典:类似对象,以key,value存贮值

class Dictionary {
    constructor() {
      this.items = {};
    }

    set(key, value) {
      this.items[key] = value;
    }

    get(key) {
      return this.items[key];
    }

    remove(key) {
      delete this.items[key];
    }

    get keys() {
      return Object.keys(this.items);
    }

    get values() {
      /*
    也可以使用ES7中的values方法
    return Object.values(this.items)
    */

      // 在这里我们通过循环生成一个数组并输出
      return Object.keys(this.items).reduce((r, c, i) => {
        r.push(this.items[c]);
        return r;
      }, []);
    }
  }
  const dictionary = new Dictionary();
  dictionary.set("Gandalf", "gandalf@email.com");
  dictionary.set("John", "johnsnow@email.com");
  dictionary.set("Tyrion", "tyrion@email.com");

  console.log(dictionary);
  console.log(dictionary.keys);
  console.log(dictionary.values);
  console.log(dictionary.items);
  
1.5 二叉树

特点:每个节点最多有两个子树的树结构

class NodeTree {
    constructor(key) {
      this.key = key;
      this.left = null;
      this.right = null;
    }
  }

  class BinarySearchTree {
    constructor() {
      this.root = null;
    }

    insert(key) {
      const newNode = new NodeTree(key);
      const insertNode = (node, newNode) => {
        if (newNode.key < node.key) {
          if (node.left === null) {
            node.left = newNode;
          } else {
            insertNode(node.left, newNode);
          }
        } else {
          if (node.right === null) {
            node.right = newNode;
          } else {
            insertNode(node.right, newNode);
          }
        }
      };
      if (!this.root) {
        this.root = newNode;
      } else {
        insertNode(this.root, newNode);
      }
    }

    //访问树节点的三种方式:中序,先序,后序
    inOrderTraverse(callback) {
      const inOrderTraverseNode = (node, callback) => {
        if (node !== null) {
          inOrderTraverseNode(node.left, callback);
          callback(node.key);
          inOrderTraverseNode(node.right, callback);
        }
      };
      inOrderTraverseNode(this.root, callback);
    }

    min(node) {
      const minNode = node => {
        return node ? (node.left ? minNode(node.left) : node) : null;
      };
      return minNode(node || this.root);
    }

    max(node) {
      const maxNode = node => {
        return node ? (node.right ? maxNode(node.right) : node) : null;
      };
      return maxNode(node || this.root);
    }
  }
  const tree = new BinarySearchTree();
  tree.insert(11);
  tree.insert(7);
  tree.insert(5);
  tree.insert(3);
  tree.insert(9);
  tree.insert(8);
  tree.insert(10);
  tree.insert(13);
  tree.insert(12);
  tree.insert(14);
  tree.inOrderTraverse(value => {
    console.log(value);
  });

  console.log(tree.min());
  console.log(tree.max());
  
2.算法篇 2.1 冒泡算法

冒泡排序,选择排序,插入排序,此处不做赘述,请戳 排序

2.2 斐波那契

特点:第三项等于前面两项之和

function fibonacci(num) { 
    if (num === 1 || num === 2) { 
        return 1
    }
    return fibonacci(num - 1) + fibonacci(num - 2)
  }
2.3 动态规划

特点:通过全局规划,将大问题分割成小问题来取最优解
案例:最少硬币找零
美国有以下面额(硬币):d1=1, d2=5, d3=10, d4=25
如果要找36美分的零钱,我们可以用1个25美分、1个10美分和1个便士( 1美分)

class MinCoinChange {

constructor(coins) {
    this.coins = coins
    this.cache = {}
}

makeChange(amount) {
    if (!amount) return []
    if (this.cache[amount]) return this.cache[amount]
    let min = [], newMin, newAmount
    this.coins.forEach(coin => {
        newAmount = amount - coin
        if (newAmount >= 0) {
            newMin = this.makeChange(newAmount)
        }
        if (newAmount >= 0 && 
             (newMin.length < min.length - 1 || !min.length) && 
             (newMin.length || !newAmount)) {
            min = [coin].concat(newMin)
        }
    })
    return (this.cache[amount] = min)
}
}

const rninCoinChange = new MinCoinChange([1, 5, 10, 25])
console.log(rninCoinChange.makeChange(36))
// [1, 10, 25]
const minCoinChange2 = new MinCoinChange([1, 3, 4])
console.log(minCoinChange2.makeChange(6))
// [3, 3]
2.4 贪心算法

特点:通过最优解来解决问题
用贪心算法来解决2.3中的案例

class MinCoinChange2 {

constructor(coins) {
    this.coins = coins
}

makeChange(amount) {
    const change = []
    let total = 0
    this.coins.sort((a, b) => a < b).forEach(coin => {
        if ((total + coin) <= amount) {
            change.push(coin)
            total += coin
        }
    })
    return change
}
}
const rninCoinChange2 = new MinCoinChange2 ( [ 1, 5, 10, 25])
console.log (rninCoinChange2. makeChange (36))

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103310.html

相关文章

  • js 排序算法快速排序

    摘要:快速排序是一种划分交换排序。快速排序基于冒泡递归分治。他在大数据情况下是最快的排序算法之一,平均事件复杂度很低而且前面的系数很小,在大量随机输入的情况下最坏情况出现的概率是极小的。 快速排序是一种划分交换排序。它采用了一种分治的策略,通常称其为分治法。 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。...

    Eidesen 评论0 收藏0
  • JS14种设计模式 (6)

    摘要:序列文章面试之函数面试之对象面试之数组的几个不操作面试之对比分析面试之数据结构与算法前言设计模式如果应用到项目中,可以实现代码的复用和解耦,提高代码质量。 showImg(https://segmentfault.com/img/bVbq2VA?w=480&h=260); 序列文章 JS面试之函数(1)JS面试之对象(2)JS面试之数组的几个不low操作(3)JS面试之http0.9~...

    luckyyulin 评论0 收藏0
  • 基本算法学习(一)希尔排序(JS)

    摘要:动态定义间隔序列参考来源详细介绍了十种算法大家可以去学习下以后大概会尽量每天更新一个算法学习吧温故而知新 参考书:严蔚敏-数据结构 希尔排序(Shells Sort) 希尔排序又称缩小增量排序,归属于插入排序一类,简单来说,和我们的插入排序比,它更快. 奇妙的记忆点: 内排序(内存排序就够了) 不稳定(排序后原始顺序无法保证) 希尔排序重点在于分割. 基本思想: 将整个待排序记录序...

    cooxer 评论0 收藏0
  • react源码ReactTreeTraversal.js数据结构算法

    摘要:面试中,经常遇到的一个简单算法题查找两个单链表的公共节点最近在读源码的时候发现一个树中对该算法的运用见函数,在此做简单的记录。地址在树中获取当前实例节点的父节点实例组件对应的,比如的表示为类组件,其为对应元素。 面试中,经常遇到的一个简单算法题:查找两个单链表的公共节点最近在读react源码的时候发现一个react树中对该算法的运用(见getLowestCommonAncestor函数...

    makeFoxPlay 评论0 收藏0
  • js中抽象相等==

    摘要:中抽象相等比较算法大致介绍一下的数据类型的数据类型分为种如果再加上数据类型,一共种与的区别描述一个空值空的对象引用即空指针,被当做一个对象,输出为算是一个吧,输出为。运算符把其值参数转换为非类型对象。 Javascript中抽象相等比较算法 undefined==null //true []==[] //false []==![] //true {}==!{} //false ![]=...

    hzx 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<