使用JavaScript实现栈、队列、链表、集合等常见数据结构。可能会有点用?

栈(Stack)

实际上JavaScript的Array本身就具有栈和队列的特性,所以我们可以借助Array来实现它们。

class Stack {constructor() {this.items = [];}get length() {return this.items.length;}// 获取栈顶元素get peek() {return this.items[this.items.length - 1];}push(element) {this.items.push(element);}pop() {this.items.pop();}
}

队列(Queue)

class Queue {constructor() {this.items = [];}get isEmpty() {return this.items.length === 0;}get length() {return this.items.length;}// 入队enqueue(element) {this.items.push(element);}// 出队dequeue() {return this.items.shift();}
}

优先队列

队列的升级版本,给每个元素一个优先级,入队时会先排序。这里PriorityQueue继承自Queue,所以只需要重写enqueue方法。

class PriorityQueue extends Queue {/*** 入队* @param {*} element 元素* @param {*} priority 优先级*/enqueue(element, priority) {const queueElement = { element, priority };if (this.isEmpty) {super.enqueue(queueElement);} else {const preIndex = this.items.findIndex(items => queueElement.priority < items.priority);if (preIndex > -1) {this.items.splice(preIndex, 0, queueElement);} else {super.enqueue(queueElement);}}}
}

循环队列

循环队列可以想象为一个首尾相连的圆环,相较于普通队列,它更节省空间。

虽然同样继承自Queue,但基本上所有方法都重写了。

class LoopQueue extends Queue {constructor(maxSize) {super();this.maxSize = maxSize;this.head = -1; //头指针this.tail = -1; //尾指针}get isFull(){return (this.tail + 1) % this.maxSize === this.head;}get isEmpty(){return this.tail === -1 && this.head === -1;}enqueue(element) {if (this.isFull) {return false;}if (this.isEmpty) {this.head = 0;}this.tail = (this.tail + 1) % this.maxSize;this.items[this.tail] = element;return true;}dequeue(){if (!this.isEmpty) {if (this.tail === this.head) {this.tail = -1;this.head = -1;} else {this.head = (this.head + 1) % this.maxSize;}return true;}return false;}
}

链表(Linked List)

// 节点
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++;}/*** 插入* @param {*} element 元素* @param {*} position 位置*/insert(element, position) {if (position >= 0 && position <= this.length) {const node = new Node(element);let current = this.head;let previous = null;if (position === 0) {this.head = node;this.head.next = current;} else {for (let index = 0; index < position; index++) {previous = current;current = current.next;}node.next = current;previous.next = node;}this.length++;return true;}return false;}/*** 删除* @param {*} position 位置*/removeAt(position) {if (position >= 0 && position < this.length) {let current = this.head;let previous = null;if (position === 0) {this.head = current.next;} else {for (let index = 0; index < position; index++) {previous = current;current = current.next;}previous.next = current.next;}this.length--;return current.element;}return null;}// 查找元素所在位置indexOf(element) {let current = this.head;let index = 0;while (current) {if (element === current.element) {return index;}index++;current = current.next;}return -1;}// 根据元素删除remove(element) {const index = this.indexOf(element);return this.removeAt(index);}toString() {let current = this.head;let string = '';while (current) {string += `${current.element} -- `;current = current.next;}string += '*';return string;}
}

集合(Set)

ES6中引入了集合类型,可以参考一下。

class Set {constructor() {this.items = {};}get size() {return Object.keys(this.items).length;}get values() {return Object.keys(this.items);}// 判断元素是否存在has(value) {return this.items.hasOwnProperty(value);}add(value) {if (!this.has(value)) {this.items[value] = value;return true;}return false;}remove(value) {if (this.has(value)) {delete this.items[value]return true;}return false;}// 并集union(otherSet) {const unionSet = new MySet();this.values.forEach((value) => unionSet.add(this.value));otherSet.values.forEach((value) => unionSet.add(otherSet.value));return unionSet;}// 交集intersection(otherSet) {const intersectionSet = new MySet();this.values.forEach((value, index) => {if (otherSet.has(value)) {intersectionSet.add(value);}});return intersectionSet;}// 差集difference(otherSet) {const differenceSet = new MySet();this.values.forEach((value) => {if (!otherSet.has(value)) {differenceSet.add(value);}});return differenceSet;}// 子集subset(otherSet) {return this.values.every((value) => otherSet.has(value));}
}

字典(Dictionary)

在JavaScript中,Object对象实际上就是字典,都是以{ key: value }的形式存储数据的。

class Dictionary {constructor() {this.items = {};}get keys() {return Object.keys(this.items);}get values() {const r = [];Object.keys(this.items).forEach((value) => {r.push(this.items[value]);});return r;}set(key, value) {this.items[key] = value;}get(key) {return this.items[key];}remove(key) {delete this.items[key];}
}

哈希表(Hash Table)

哈希表也是以键值对的形式存储数据的,但是因为每个数据都会根据key生成唯一的哈希值,所以查询速度非常快。

这里散列函数就是用来生成哈希值的,随便写的,常用的构造散列函数的方法在网上能查到很多。

class HashTable {constructor() {this.table = [];}// 散列函数getHashCode(key) {let hash = 0;for (let i = 0; i < key.length; i++) {hash += key.charCodeAt(i);}return hash % 64 * 0xffffff;}put(key, value) {const position = this.getHashCode(key);this.table[position] = value;}get(key) {return this.table[this.getHashCode(key)];}remove(key) {this.table[this.getHashCode(key)] = undefined;}
}

树(tree)

正常的二叉树没有必要实现,这里实现一下二叉搜索树。

class Node {constructor(data) {this.data = data;this.left = null;this.right = null;}
}
class BinarySearchTree {constructor() {this.root = null;}insert(data) {const newNode = new Node(data);const insertNode = (node, newNode) => {if (newNode.data < node.data) {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.data);inOrderTraverseNode(node.right, callback);}}inOrderTraverseNode(this.root, callback);}// 先序遍历preOrderTraverse(callback) {const preOrderTraverseNode = (node, callback) => {if (node !== null) {callback(node.data);preOrderTraverseNode(node.left, callback);preOrderTraverseNode(node.right, callback);}}preOrderTraverseNode(this.root, callback);}// 后序遍历postOrderTraverse(callback) {const postOrderTraverseNode = (node, callback) => {if (node !== null) {postOrderTraverseNode(node.left, callback);postOrderTraverseNode(node.right, callback);callback(node.data);}}postOrderTraverseNode(this.root, callback);}min() {let current = this.root;while (current.left !== null) {current = current.left;}return current.data;}max() {let current = this.root;while (current.right !== null) {current = current.right;}return current.data;}search(data) {let current = this.root;while (current.data !== data) {if(data < current.data) {current = current.left;} else {current = current.right;}if (current == null) {return null;}}return current;}remove(data) {const removeNode = (node, data) => {if (node === null) {return false;}if (node.data === data) {if (node.left === null && node.right === null) {return null;}if (node.left === null) {return node.right;}if (node.right === null) {return node.left;}let tempNode = node.right;while(tempNode.left !== null) {tempNode = tempNode.left;}node.data = tempNode.data;node.right = removeNode(node.right, tempNode.data);return node;}if (node.data > data) {node.left = removeNode(node.left, data);return node;} if(node.data < data) {node.right = removeNode(node.right, data);return node;}}this.root = removeNode(this.root, data);}
}

图(Graph)

这里实现的无向图。

class Graph {constructor() {this.vertices = []; // 存顶点this.adjList = {}; // 存边}// 顶点addVertex(v) {this.vertices.push(v);this.adjList[v] = [];}// 边addEdge(v, w) {this.adjList[v].push(w);this.adjList[w].push(v);}// 转化成邻接表的形式的字符串toString() {let str = '\n';for (let i = 0; i < this.vertices.length; i++) {const v = this.vertices[i];str += v + ' => ';const e = this.adjList[v];for (let j = 0; j < e.length; j++) {str += ' ' + e[j] + ' ';}str += '\n';}return str;}
}

参考文章

  • 在 JavaScript 中学习数据结构与算法

  • 常见数据结构和Javascript实现总结

JavaScript实现常见的数据结构相关推荐

  1. JavaScript 中常见设计模式整理

    开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式.本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知. JavaScript 中常见设计模 ...

  2. 2021年Javascript最常见的面试题以及答案

    Js面试题以及答案(建议收藏,面试必过!) 从输入 URL 到页面展示,这中间发生了什么? JavaScript的数据类型及其检测? typeof 和 instanceof 的区别? 对栈和堆内存有了 ...

  3. php中常见的错误类型有,JavaScript中常见的错误类型有哪些?(详细介绍)

    在JavaScript中,当发生错误时会生成描述错误类型的错误对象,此错误对象包含错误类型和编号等信息,这些信息可用于后续处理等,在本篇文章中将给大家介绍常见的错误类型以及如何处理这些错误. Java ...

  4. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  5. 一文梳理JavaScript中常见的七大继承方案

    阐述JavaScript中常见的七大继承方案

  6. JavaScript:JavaScript中常见获取对象元素的方法

    介绍: javascript中常见的3种获取元素的方法,分别是通过元素ID.通过标签名字和通过类名字来获取 操作如下: 1.getElementById DOM提供了一个名为getElementByI ...

  7. python 长度queue_python:常见的数据结构

    ​ Python中常见的数据结构可以统称为容器.序列(如列表和元组).映射(如字典)以及集合(set)是三类主要的容器.线性数据结构分类:栈(stack)--先进后出. 队列(queue)-先进先出. ...

  8. java 用户名不为空_[Java教程]【关于JavaScript】常见表单用户名、密码不能为空

    [Java教程][关于JavaScript]常见表单用户名.密码不能为空 0 2015-05-31 12:00:14 在论坛等系统的用户注册功能中,如果用户忘记填写必填信息,如用户名.密码等,浏览器会 ...

  9. python常见的数据结构

    Python中常见的数据结构可以统称为容器.序列(如列表和元组).映射(如字典)以及集合(set)是三类主要的容器. 线性数据结构分类:栈(stack)--先进后出. 队列(queue)-先进先出.双 ...

最新文章

  1. TVM vs TensorRT比较
  2. 专访梅耶·马斯克:硅谷钢铁侠是怎样被炼成的?
  3. linux多线程编程5--信号量(semaphore)
  4. 3D卷积GAN飞起!微软“可缩放”新框架只需2D数据即可生成逼真3D模型
  5. php接收get参数false是字符串,php怎么接收url参数
  6. vue+nodejs 将canvas发布到dlna投屏服务
  7. jQuery学习笔记——筛选元素集合
  8. hdu 2255+hdu 3395
  9. Premiere CC2019软件下载和安装教程
  10. STM32——PS2遥控手柄
  11. 关键字查询地理经纬度及省份-市
  12. PostgreSQL数据类型(中文手册)
  13. Python实现繁体字和简体字的相互转换
  14. @Controller注解的一些理解吧
  15. 一分钟让你知道如何删除PDF其中几页
  16. Windows10 插入耳机没声音,安装驱动无效问题解决
  17. pn532写入手机nfc_NFC的PN532 读写命令格式
  18. PAT B1032. 挖掘机技术哪家强 (20)
  19. 李开复:长尾效应带给媒体的不是威胁
  20. HP pavilion g4笔记本详细拆机图解

热门文章

  1. 数学建模中常用的方法
  2. 查看linux中shell的几种方法汇总
  3. oracle数据库查询表的列
  4. 并查集——小米笔试题求朋友圈个数,分小组个数
  5. 【OpenCV】入门学习资料汇总
  6. Linux—vim/vi 翻页跳转命令快捷键
  7. MySQL—Mysql与MariaDB启停命令的区别
  8. 使用switch case语句来显示月份的对应天数
  9. 草稿django添加自定义模板代码的用法
  10. django-正向查找