在过去的几周中,我一直在阅读Jay Wengrow的《数据结构和算法指南》。如果您已经有一些经验编程,并且想提高对这些主题的了解,那么这本书就很棒。到目前为止,算法零件很棒,但是如果您问我,对我来说,最有见地和最有见地的部分是数据的结构。
如果您来自CS学位或类似的背景,这些主题可能是小菜一碟,当然您会熟悉它。但是,对于那些来自截然不同的背景并制作训练营或自学成才的人来说,这些主题有时会被忽略。因为当我们开始时,我们教会我们的代码最初应该工作。如果我们开始开始,但是稍后我们开始获得更多的经验,除了找到有效的代码外,我们还应该找到有效和可读代码。
这就是数据结构的到来。是的,他们给了我们结构和顺序。但是,最重要的是,它们帮助我们实现效能,因为每个结构在每个上下文和操作中的表现都不同。
数据结构操作
了解任何数据结构的性能,我们通常会参考四个基本操作:阅读,搜索,插入和删除。
数组
阵列是计算机科学中最基本的数据结构。从本质上讲,一个数组是大量内存,您可以在其中存储简单的数据元素列表。阵列具有非常有用的属性,是他们的长度。此属性向我们返回数组中的元素数量。另外,数组中的每个元素都有一个索引:一个数字,该数字标识了其存储在数组中的数据。在效率方面,读取阵列内部的元素非常有效,这将使我们花费一步。为了进行搜索,它将取决于我们使用的搜索算法,但是例如,如果我们使用线性搜索,则用于n个元素的数组,它可能会花费我们最大的n个步骤。插入可能会使我们最大的n + 1步骤(如果我们要在数组的第一个索引中插入元素,就是这种情况)。另一方面,删除可能最多需要n个步骤。如我们所见,在数组结束时插入和删除元素非常有效,但是如果我们想在数组的开始时进行此操作,它将不会具有相同的功能。
let animals = ['dog', 'cat', 'lion', 'bird'];
// Length property
console.log(animals.length); // 4
// Reading. Want to know the value stored in certain index
console.log(animals[2]); // 'lion'
// Searching.
// Want to know if a string of value 'bird',
// and if it exist, we want to know the index
const valueToFind = 'bird';
const indexOfValue = animals.findIndex((animal, index) => {
console.log(`${index + 1} step`);
return animal === valueToFind;
});
console.log(indexOfValue);
// Counting steps
// '1 steps'
// '2 steps'
// '3 steps'
// '4 steps'
// Index of the searched value
// '3'
// Inserting
// First, in the end of the array
animals.push('wolf');
console.log(animals); // ['dog', 'cat', 'lion', 'bird', 'wolf']
// Now in the middle
animals.splice(1, 0, 'tiger');
console.log(animals); // ['dog', 'tiger, 'cat', 'lion', 'bird', 'wolf']
// Deleting
//First, in the end of the array
animals.pop();
console.log(animals); // ['dog', 'tiger, 'cat', 'lion', 'bird']
// Now in the middle
animals.splice(2, 1);
console.log(animals); // ['dog', 'tiger, 'lion', 'bird']
哈希表(对象)
哈希表是配对值的列表。该对中的第一项称为键,第二个项目称为 value 。这种结构中最大的好处是阅读和插入非常快。另外,如果我们有成对相关的数据,则哈希表是组织数据的自然数据结构。例如,如果您有一个物品列表的价格:
{'Blue jean': 105, 'Yellow shirt': 45, 'Green Jacket': 78}
哈希表的魔力在于键值的配对。因此,阅读和插入的成本为o(1)(一步)。如果我们不知道钥匙,我们将无法利用这些好处。
在JavaScript中,哈希表的最常见实现是对象。在对象中,我们可以将密钥与值或函数配对。这些值称为属性,函数称为方法。为了访问或读取键的值,我们可以使用点表示法(object.key)或括号符号(object ['key'])符号。
const myHashTable = {
prop1: 'I am the value of this property or key.',
method1: function () {
console.log('I am logging inside a method');
},
};
console.log(myHashTable.prop1); // 'I'm the value of this property or key'
// Calling the method with bracket ([]) notation
myHashTable['method1'](); // 'I am logging inside a method'
插入和删除,我们可以看到下一个示例:
const myObject = {
prop1: 'Hello',
};
myObject.insertedProp = 'I am inserted';
delete myObject.prop1;
console.log(myObject); // { insertedProp: "I am inserted" }
此外,JavaScript中的Hash表的另一个实现是地图。它们类似于对象,但具有重要差异。例如,地图中的键可以是任何值(函数,对象或任何原始)。在对象中,键必须是字符串或符号。另外,地图是一个迭代的,该对象不会自然地实现迭代协议。如果您有兴趣查看所有差异,则可以在MDN documentation中检查。
套
集合是一种数据结构,不允许重复值包含在其中。这是一个简单的值列表,但仅允许唯一值的约束。 JavaScript使用哈希表实现集合。
// Create Set
const mySet = new Set();
// Insetions
// For insertion we use the method .add()
mySet.add(1); // Set(1) { 1 }
mySet.add(5); // Set(2) { 1, 5 }
// Doesn't allow inserting a repeted value
mySet.add(5); // Set(2) { 1, 5 }
// Searching
// For searching and checking if a value exist,
// we use the method .has()
mySet.has(1); // true
mySet.has('dog'); // false
// Delete
mySet.delete(5); // Removes 5 from set
mySet.has(5); // false
我们可以提供的最有用的用途之一是消除数组中的重复数据:
// Use to remove duplicate elements from an array
const numbers = [2, 3, 2, 4, 4, 5, 21];
// Here we make a Set starting from an array
// The conversion eliminate duplicate data
// Later we transform the Set to an array using the spread operator (...)
console.log([...new Set(numbers)]);
// [2, 3, 4, 5, 21]
在下一篇文章中,我们将继续查看其他数据结构,例如堆栈,队列和其他数据结构。
感谢您的阅读。在下一篇文章中见。