能更好地理解数据结构的工作方式

听起来熟悉吗?“我结束了在线课程,开始开发前端。”

可以为计算机科学特别是数据结构和算法的改进寻求基础。今天将介绍一些常见的数据结构,并使用JavaScript实现。

希望这部分能补充大家的技术!

1.堆叠堆栈

堆栈遵循LIFO(后进先出)的原理。堆积书的话,最上面的书会在最下面的书前面。或者,在浏览互联网时,按“后退”按钮可转至最近访问的页面。

Stack有以下常用方法:

推式:输入新元素

Pop:删除顶部元素并返回删除的元素

Peek:返回顶部元素

长度:返回堆栈中元素的数量

Javascript中的数组具有Stack的属性,但使用Stack()函数从头开始构建Stack

Function Stack() {

=0;

={ };

=function(值){

[]=值;

中选择另一种天花板类型。

}

=function () {

If (===0) {

Return undefined

}

-;

var result=[];

删除[];

Return result

}

=function () {

return[-1];

}

=function () {

Return

}

}2 .队列队列

队列类似于堆栈。唯一的区别是Queue使用FIFO原理(先进先出)。也就是说,在等公交车的时候,队列中的第一个总是第一个。

队列有以下方法:

排入伫列:输入伫列并将元素新增至结尾

出队:结束队列,移去旧元素,然后返回

Front:汇入第一个零件

Isempty:确定队列是否为空

大小:获取队列中的元素数)

JavaScript中的数组具有Queue的某些属性,因此可以使用数组构造Queue的示例。

Function Queue() {

var collection=[];

=function () {

集合(con);

}

=function(元素){

COLLEC(ELEMEMENT);

}

=function () {

return collec();

}

=function () {

return collection[0];

}

=function () {

Return collec====

}

=function () {

Return collec

}

}优先级队列

队列有另一个高级版本。为每个元素指定优先级,并按优先级排序。

Function PriorityQueue() {

.

=function(元素){

if(){

COLLEC(ELEMEMENT);

} else

Var added=false

for(var I=0;I collecI) {

If (element [1]集合[I] [1]) {

Collec(i,0,element);

Added=true

布雷克;

}

}

If(!Added) {

COLLEC(ELEMEMENT);

}

}

}

}测试:

var pQ=new priority queue();

([gannicus,3]);

([Spartacus,1]);

([crixus,2]);

([奥诺玛默斯,4]);

();结果:

[

[Spartacus,1],

[crix

us , 2 ], [ gannicus , 3 ], [ oenomaus , 4 ] ]

3.链表

从字面上看,链表是一个链式数据结构,每个节点由两部分信息组成:该节点的数据和指向下一个节点的指针。 链表和常规数组都是带有序列化存储的线性数据结构。 当然,它们也有差异:

单边链表通常具有以下方法:

· size:返回节点数

· head:返回head的元素

· add:在尾部添加另一个节点

· delete:删除某些节点

· indexOf:返回节点的索引

· elementAt:返回索引的节点

· addAt:在特定索引处插入节点

· removeAt:删除特定索引处的节点

/** Node in the linked list **/ function Node(element) { // Data in the node = element; // Pointer to the next node = null; } function LinkedList() { var length = 0; var head = null; = function () { return length; } = function () { return head; } = function (element) { var node = new Node(element); if (head == null) { head = node; } else { var currentNode = head; while ) { currentNode = curren; } curren = node; } length++; } = function (element) { var currentNode = head; var previousNode; if === element) { head = curren; } else { while !== element) { previousNode = currentNode; currentNode = curren; } = curren; } length--; } = function () { return length === 0; } = function (element) { var currentNode = head; var index = -1; while (currentNode) { index++; if === element) { return index; } currentNode = curren; } return -1; } At = function (index) { var currentNode = head; var count = 0; while (count < index) { count++; currentNode = curren; } return curren; } At = function (index, element) { var node = new Node(element); var currentNode = head; var previousNode; var currentIndex = 0; if (index > length) { return false; } if (index === 0) { node.next = currentNode; head = node; } else { while (currentIndex < index) { currentIndex++; previousNode = currentNode; currentNode = curren; } node.next = currentNode; = node; } length++; } At = function (index) { var currentNode = head; var previousNode; var currentIndex = 0; if (index < 0 || index >= length) { return null; } if (index === 0) { head = curren; } else { while (currentIndex < index) { currentIndex++; previousNode = currentNode; currentNode = curren; } = curren; } length--; return curren; } }

4.集合

集合是数学的基本概念:定义明确且不同的对象的集合。 ES6引入了集合的概念,它与数组有一定程度的相似性。 但是,集合不允许重复元素,也不会被索引。

一个典型的集合具有以下方法:

· values:返回集合中的所有元素

· size:返回元素数

· has:确定元素是否存在

· add:将元素插入集合

· delete:从集合中删除元素

· union:返回两组的交集

· difference:返回两组的差异

· subset:确定某个集合是否是另一个集合的子集

为了区分ES6中的集合,在以下示例中我们声明为MySet:

function MySet() { var collection = []; = function (element) { return (element) !== -1); } = function () { return collection; } = function () { return collec; } = function (element) { if (!(element)) { collec(element); return true; } return false; } = function (element) { if ((element)) { index = collec(element); collec(index, 1); return true; } return false; } = function (otherSet) { var unionSet = new MySet(); var firstSet = (); var secondSet = o(); (function (e) { unionSet.add(e); }); (function (e) { unionSet.add(e); }); return unionSet; } = function (otherSet) { var intersectionSet = new MySet(); var firstSet = (); (function (e) { if (e)) { in(e); } }); return intersectionSet; } = function (otherSet) { var differenceSet = new MySet(); var firstSet = (); (function (e) { if (!o(e)) { di(e); } }); return differenceSet; } = function (otherSet) { var firstSet = (); return (function (value) { return o(value); }); } }

5.哈希表

哈希表是键值数据结构。 由于通过键查询值的闪电般的速度,它通常用于Map,Dictionary或Object数据结构中。 如上图所示,哈希表使用哈希函数将键转换为数字列表,这些数字用作相应键的值。 要快速使用键获取价值,时间复杂度可以达到O(1)。 相同的键必须返回相同的值-这是哈希函数的基础。

哈希表具有以下方法:

· add:添加键值对

· delete:删除键值对

· find:使用键查找对应的值

Java简化哈希表的示例:

function hash(string, max) { var hash = 0; for (var i = 0; i < ; i++) { hash += (i); } return hash % max; } function HashTable() { let storage = []; const storageLimit = 4; = function (key, value) { var index = hash(key, storageLimit); if (storage[index] === undefined) { storage[index] = [ [key, value] ]; } else { var inserted = false; for (var i = 0; i < storage[index].length; i++) { if (storage[index][i][0] === key) { storage[index][i][1] = value; inserted = true; } } if (inserted === false) { storage[index].push([key, value]); } } } = function (key) { var index = hash(key, storageLimit); if (storage[index].length === 1 && storage[index][0][0] === key) { delete storage[index]; } else { for (var i = 0; i < storage[index]; i++) { if (storage[index][i][0] === key) { delete storage[index][i]; } } } } = function (key) { var index = hash(key, storageLimit); if (storage[index] === undefined) { return undefined; } else { for (var i = 0; i < storage[index].length; i++) { if (storage[index][i][0] === key) { return storage[index][i][1]; } } } } }

6.树

树数据结构是多层结构。 与Array,Stack和Queue相比,它也是一种非线性数据结构。 在插入和搜索操作期间,此结构非常高效。 让我们看一下树数据结构的一些概念:

· root:树的根节点,无父节点

· parent 父节点:上层的直接节点,只有一个

· children 子节点:较低层的直接节点,可以有多个

· siblings 兄弟姐妹:共享同一父节点

· leaf 叶:没有子节点

· edge 边缘:节点之间的分支或链接

· path 路径:从起始节点到目标节点的边缘

· height of node 节点高度:特定节点到叶节点的最长路径的边数

· height of tree 树的高度:根节点到叶节点的最长路径的边数

· depth of node 节点深度:从根节点到特定节点的边数

· degree of node 节点度:子节点数

这是二叉搜索树的示例。 每个节点最多有两个节点,左节点小于当前节点,右节点大于当前节点:

二进制搜索树中的常用方法:

· add:在树中插入一个节点

· findMin:获取最小节点

· findMax:获取最大节点

· find:搜索特定节点

· isPresent:确定某个节点的存在

· delete:从树中删除节点

JavaScript中的示例:

class Node { constructor(data, left = null, right = null) { = data; = left; = right; } } class BST { constructor() { = null; } add(data) { const node = ; if (node === null) { = new Node(data); return; } else { const searchTree = function (node) { if (data < node.data) { if === null) { node.left = new Node(data); return; } else if !== null) { return searchTree); } } else if (data > node.data) { if === null) { node.right = new Node(data); return; } else if !== null) { return searchTree); } } else { return null; } }; return searchTree(node); } } findMin() { let current = ; while !== null) { current = current.left; } return current.data; } findMax() { let current = ; while !== null) { current = current.right; } return current.data; } find(data) { let current = ; while !== data) { if (data < current.data) { current = current.left } else { current = current.right; } if (current === null) { return null; } } return current; } isPresent(data) { let current = ; while (current) { if (data === current.data) { return true; } if (data < current.data) { current = current.left; } else { current = current.right; } } return false; } remove(data) { const removeNode = function (node, data) { if (node == null) { return null; } if (data == node.data) { // no child node if == null && node.right == null) { return null; } // no left node if == null) { return node.right; } // no right node if == null) { return node.left; } // has 2 child nodes var tempNode = node.right; while !== null) { tempNode = ; } node.data = ; node.right = removeNode, ); return node; } else if (data < node.data) { node.left = removeNode, data); return node; } else { node.right = removeNode, data); return node; } } = removeNode(, data); } }

测试一下:

const bst = new BST(); b(4); b(2); b(6); b(1); b(3); b(5); b(7); b(4); con()); con()); b(7); con()); con(4));

结果:

1 7 6 false

7.Trie(发音为" try")

Trie或"前缀树"也是一种搜索树。 Trie分步存储数据-树中的每个节点代表一个步骤。 Trie用于存储词汇,因此可以快速搜索,尤其是自动完成功能。

Trie中的每个节点都有一个字母-在分支之后可以形成一个完整的单词。 它还包含一个布尔指示符,以显示这是否是最后一个字母。

Trie具有以下方法:

· add:在字典树中插入一个单词

· isWord:确定树是否由某些单词组成

· print:返回树中的所有单词

/** Node in Trie **/ function Node() { = new Map(); = false; = function () { = true; }; = function () { return ; } } function Trie() { = new Node(); = function (input, node = ) { if === 0) { node.setEnd(); return; } else if (!node.keys.has(input[0])) { node.keys.set(input[0], new Node()); return (1), node.keys.get(input[0])); } else { return (1), node.keys.get(input[0])); } } = function (word) { let node = ; while > 1) { if (!node.keys.has(word[0])) { return false; } else { node = node.keys.get(word[0]); word = word.substr(1); } } return (word) && node.keys.get(word).isEnd()) ? true : false; } = function () { let words = new Array(); let search = function (node = , string) { if != 0) { for (let letter of node.keys.keys()) { searc(letter), (letter)); } if ()) { words.push(string); } } else { > 0 ? words.push(string) : undefined; return; } }; search(, new String()); return words.length > 0 ? words : null; } }

8.图

图(有时称为网络)是指具有链接(或边)的节点集。 根据链接是否具有方向,它可以进一步分为两组(即有向图和无向图)。 Graph在我们的生活中得到了广泛使用,例如,在导航应用中计算最佳路线,或者在社交媒体中向推荐的朋友举两个例子。

图有两种表示形式:

邻接表

在此方法中,我们在左侧列出所有可能的节点,并在右侧显示已连接的节点。

邻接矩阵

邻接矩阵显示行和列中的节点,行和列的交点解释节点之间的关系,0表示未链接,1表示链接,> 1表示不同的权重。

要查询图中的节点,必须使用"广度优先"(BFS)方法或"深度优先"(DFS)方法在整个树形网络中进行搜索。

让我们看一个用Javascript编写BFS的示例:

function bfs(graph, root) { var nodesLen = {}; for (var i = 0; i < gra; i++) { nodesLen[i] = Infinity; } nodesLen[root] = 0; var queue = [root]; var current; while != 0) { current = queue.shift(); var curConnected = graph[current]; var neighborIdx = []; var idx = curConnec(1); while (idx != -1) { neig(idx); idx = curConnec(1, idx + 1); } for (var j = 0; j < neig; j++) { if (nodesLen[neighborIdx[j]] == Infinity) { nodesLen[neighborIdx[j]] = nodesLen[current] + 1; queue.push(neighborIdx[j]); } } } return nodesLen; }

测试一下:

var graph = [ [0, 1, 1, 1, 0], [0, 0, 1, 0, 0], [1, 1, 0, 0, 0], [0, 0, 0, 1, 0], [0, 1, 0, 0, 0] ]; con(bfs(graph, 1));

结果:

{ 0: 2, 1: 0, 2: 1, 3: 3, 4: Infinity }

就是这样–我们涵盖了所有常见的数据结构,并提供了JavaScript中的示例。 这应该使您更好地了解计算机中数据结构的工作方式。 编码愉快!

(本文翻译自Kingsley Tan的文章《8 Common Data Structures in Javascript》, 参考 )

1.《【crixus】JavaScript的八种常见数据结构》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《【crixus】JavaScript的八种常见数据结构》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/yule/2254751.html