什么是数据结构?
下面是维基百科的解释:
数据结构是计算机存储、组织数据的方式。数据结构意味着接口或封装:一个数据结构可被视为两个函数之间的接口,或者是由数据类型联合组成的存储内容的访问方法封装。
我们每天的编码中都会用到数据结构,下面是常见的数据结构:
- 数组(Array)
- 栈(Stack)
- 队列(Queue)
- 链表(Linked List)
- 散列表(Hash)
- 字典
- 树(Tree)
- 图(Graph)
- 堆(Heap)
数组(Array)
在计算机科学中,数组数据结构(英语:array data
structure),简称数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址。——维基百科
数组经常使用的场景:待办事项列表、购物清单、最佳十名榜单等等。
数组是计算机科学中的一种数据结构,用于存储一系列相同类型的元素,并将它们存在连续的内存中。通过索引可以找到存储地址。
适用场景
- 适用:简单数据结构、不需要频繁查找或排序
- 不适用:复杂数据结构、需要频繁操作和查找
创建数组
Array
构造函数:new Array()
或new Array(1, 2, 3)
,需要new
关键字- 方括号
[]
:[]
或[1, 2, 3]
,更简洁
1、Array
构造函数
var arr1 = new Array(); //创建空数组
var arr2 = new Array(1,2,3); //创建元素为1,2,3的数组
var arr3 = new Array(5); //创建长度为5的数组
Array构造函数,需要使用new
关键字。
2、使用方括号[]
var arr1 = [] ; //创建一个空数组
var arr2 = [4,5,6]; //创建元素为4,5,6的数组
判断、长度和遍历数组
Array.isArray(arr)
:判断是否是数组arr.length
:获取数组长度- 遍历方式:
for
、forEach
、map
、filter
、some
、every
、find
判断是否是数组
Array.isArray(arr)
判断
Array.isArray(arr1);
结果输出为: true
判断数组的长度
数组有一个属性length,可以用来获取数组的长度。
var arr2 = [4,5,6,7];
var length = arr2.length;
结果输出为: 4
遍历数组
方式一:for循环遍历数组
for(var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
方式二:forEach遍历数组
forEach()在原数组的基础上改变,没有返回值,在function内进行操作
arr.forEach( function (i) {
console.log(i);
});
方式三:map遍历数组
map()会返回一个新数组,原数组不会改变。
var arr = [1,2,3];
var arr1 = arr.map(function (i) {
return i * i;
});
结果:arr1 = [1,4,9]
方式四:filter遍历数组
过滤筛选,返回一个新数组,原数组不会改变。
var arr = [1,2,3,4,5,6,7,8,9];
var arr1 = arr.filter(function(i) {
return i%2==0;
});
结果:arr1 = [2,4,6,8]
方式五:some遍历检测数组中是否有元素满足条件
如果有一个元素满足条件,则返回true,剩下的元素不会再进行检测
如果全部遍历结束,没有满足条件的元素,则返回false
var arr = [10,17,12,11];
arr.some(function(i){
return i >15;
);
结果:true
方式六:every遍历检测数组是否所有元素都满足条件
var arr = [17,10,18,15];
arr.every(function(i){
return i > 11;
});
结果:false
方法七:find遍历返回通过测试的数组的第一个元素的值
当数组中的元素满足条件时,find()返回符合条件的这个元素,剩下的元素不会再进行检测
如果没有符合条件的元素则返回undefined
var arr = [10,12,15,19,111];
arr.find(function(i){
return i > 14;
});
结果:15
基本操作
- 读取/查找:
arr[index]
、indexOf
、lastIndexOf
- 更新/替换:直接赋值或使用
splice()
插入和删除元素
- 插入:
unshift()
(首部)、push()
(尾部)、splice()
(中间) - 删除:
pop()
(尾部)、shift()
(首部)、splice()
(中间)
读取元素/查找运算
JavaScript 中通过 数组[下标]
的方式来访问数组中指定下标的元素值,数组下标从0开始。
let arr = [1,5,2,4,4,3,2,14]
console.log(arr[5]) // 3
indexOf()
查找某个字符串在要查询的字符串中首次出现的位置的索引值
var arr = [1,2,3,4,3,2,1];
var n = arr.indexOf(3);
结果: n = 2;
lastIndexOf()
查找某个字符串在要查询的字符串中最后一个出现的索引值
var arr = [1,2,3,4,3,2,1];
var n = arr.lastIndexOf(3);
结果:n = 4;
注意:如果某字符串中只有一个要查询的字符串,那么lastIndexOf和indexOf结果是一样的。
更新元素/替换元素
数组元素值的更新原理与访问原理一致,也是通过先计算出要更新的内存区域,然后再对其进行修改。
JavaScript 中通过 数组[下标] = 值
的方式对数组中指定位置的值进行修改。
let arr = [1,5,2,4,4,3,2,14]
arr[5] = 100
console.log(arr[5]) // 100
splice()方法
splice(index,length,new_arr)
- index:从第几个元素开始替换
- length:需要替换的元素的个数
- new_arr:替换出来的元素存储在new_arr里
这个方法的返回结果是被截取的部分
使用splice()进行替换:
var arr = [1,2,3,4,5,6];
var arr1 = arr.splice(0,2,9);
结果:arr = [9,3,4,5,6]; arr1 = [1,2];
使用splice()进行删除:
var arr = [1,2,3,4,5,6];
arr.splice(2,3);
结果:arr = [1,2,6]; arr1 = [3,4,5];
使用splice()进行插入:
var arr = [1,2,3,4,5,6];
arr.splice(2,0,10,11,12);
结果:arr = [1,2,10,11,12,3,,4,5,6];
插入元素/添加元素
数组的实际元素数量有可能小于数组的长度
let arr = new Array(8); //定义长度为8的数组,在内存中会为我们分配8个元素的空间
// 初始化:对数组前6个元素赋值
arr[0] = 1;
arr[1] = 5;
arr[2] = 2;
arr[3] = 4;
arr[4] = 4;
arr[5] = 3;
arr.size = 5 // 代表当前数组的实际使用长度
首位插入
unshift()
向数组首位插入元素,可插入多个
var arr = [1,2,3,4,5,6];
arr.unshift(0);
结果:arr = [0,1,2,3,4,5,6];
尾部插入
尾部插入,是最简单的情况,直接把插入的元素放在数组尾部的空闲位置即可,等同于更新元素的操作
如果需要在数组最后插入一个1,直接对当前数组最后一项赋值即可
arr[6] = 1 // 对第6个元素赋值
console.log(arr) // [ 1, 5, 2, 4, 4, 3, 1, <1 empty item> ]
push()
向数组末位插入入元素,可插入多个
var arr = [1,2,3,4,5,6];
arr.push(7);
结果:arr = [1,2,3,4,5,6,7];
配合length使用
向数组末位插入一个元素
var arr = [1,2,3,4,5,6];
ar[arr.length] = 8;
结果:arr = [1,2,3,4,5,6,8];
中间插入
由于数组的每一个元素都有其固定下标,所以不得不首先把插入位置及后面的元素向后移动,腾出地方,再把要插入的元素放到对应的数组位置上;
如果需要在数组第三个位置后插入一个1,那么需要想将第三个位置以及后面的元素全部向后移动一位,留出空闲的位置后再对其进行修改操作。
// 向数组中下标为 index 的位置插入一个item值
function arrayAddItem(arr, index, item) {
// 将第item后的元素全部向后移动一位
for(let i = arr.size; i > index; i--){
// 移动
arr[i] = arr[i-1]
}
// 将要插入的值赋值到指定位置
arr[index] = item
arr.size++
return arr
}
arr = arrayAddItem(arr, 3, 1)
console.log(arr); // [ 1, 5, 2, 1, 4, 4, 3, <1 empty item> ]
超范围插入
由于数组的长度是不可变的,所以一个数组分配到的内存空间也是固定的。前面都是在数组中元素数量小于数组长度的情况下插入元素的。
let arr = [1,2,3,4,5]
arr.size = 5 // 当前数组是使用长度
// 向数组中下标为 index 的位置插入一个item值
function arrayAddItem(arr, index, item) {
if(arr[arr.length-1]){
// 数组中的元素数量已经满了,扩容数组
arr = expandArray(arr)
}
// 将第item后的元素全部向后移动一位
for(let i = arr.size; i > index; i--){
// 移动
arr[i] = arr[i-1]
}
// 将要插入的值赋值到指定位置
arr[index] = item
arr.size++
return arr
}
// 扩容数组为原来长度的两倍
function expandArray(arr){
// 创建一个长度为原来长度两倍的数组
let newArray = new Array(arr.size * 2)
// 将原来的数组复制到新的数组中
for (let i = 0; i < arr.size; i++) {
newArray[i] = arr[i]
}
newArray.size = arr.size
return newArray
}
arr = arrayAddItem(arr, 3, 1)
console.log(arr); [ 1, 2, 3, 1, 4, 5, <4 empty items>]
删除元素
数组的删除操作和插入操作的过程相反,如果删除的元素位于数组中间,其后的元素都需要向前挪动1位
function arrayRemoveItem(arr, index){
for (let i = index; i < arr.size-1; i++) {
// 后面一项往前移动
arr[i] = arr[i+1]
}
// 当前项算法为最后一项
delete arr[arr.size-1]
arr.size--
return arr
}
如果对数组元素没有顺序要求,删除操作还存在一种取巧的方法:
function arrayRemoveItem(arr, index){
// 最后一项移动到被删除的位置
arr[index] = arr[size-1]
// 移除最后一项
delete arr[size-1]
size--
return arr
}
pop()
把数组末尾的元素去除,并返回这个元素
var arr = [1,2,3,4,5,6];
var number = arr.pop();
结果:arr = [1,2,3,4,5]; number = 6;
shift()
把数组开头的元素去除,并返回这个元素
var arr = [1,2,3,4,5,6];
var number = arr.shift();
结果:arr = [2,3,4,5,6]; number = 1;
其他操作
- 排序和反序:
sort()
、reverse()
- 连接:
concat()
- 转换为字符串:
join()
、toString()
- 填充:
fill()
反序reverse()
用来反转数组的
var arr = [1,2,3,4];
arr.reverse();
结果:arr = [4,3,2,1];
排序sort()
按照字典顺序对元素进行排序,用来排序数组的,并且你也可以自定义排序规则,只需要传入一个函数即可
var arr = [8,5,6,2,3,1];
arr.sort();
结果:arr = [1,2,3,5,6,8];
arr = ['sunshine_lin','sanxin_lin','digger_lin']
console.log(arr.sort())
//['digger_lin','sanxin_lin','sunshine_lin' ]
console.log(arr)
//['digger_lin','sanxin lin','sunshine lin'
console.log(arr.sort((a,b) => b,length - a.length)) // 根据字符串长度排序
//['sunshine_lin','digger_lin','sanxin_lin' ]
console.log(arr)
// [ 'sunshine_lin','digger_lin','sanxin_lin']
连接concat()
连接两个或者多个数组,并且返回该数组。
var arr1 = [1,2,3];
var arr2 = [4,5,6];
arr1.concat(arr2);
结果:arr1 = [1,2,3,4,5,6];
数组转换为字符串
join()
var arr = [1,2,3,4,5];
arr.join();
结果为:"1,2,3,4,5"
toString()
var arr = ["a","b","c","d"];
arr.toString();
结果为:“a,b,c,d”
fill 填充
用来把数组填满成自己想要的元素
arr = ['sunshine_lin','sanxin_lin','digger_lin']
console.log(arr.fill(0))
// [0, 0, 0]
console.log(arr)
// [0, 0, 0]
console.log(new Array(5).fill('哈哈哈哈哈哈'))
// ['哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈', '哈哈哈哈哈哈']
参考效果
参考代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Array操作示例</title>
</head>
<body>
<script>
var arr = [1, 2, 3, 4, 5]; // 创建数组
// 判断、长度和遍历数组
console.log(Array.isArray(arr)); // true
console.log(arr.length); // 5
arr.forEach(function (item) {
console.log(item);
});
// 读取/查找
console.log(arr[2]); // 3
console.log(arr.indexOf(4)); // 3
console.log(arr.lastIndexOf(2)); // 1
// 更新/替换
arr[1] = 6;
console.log(arr); // [1, 6, 3, 4, 5]
arr.splice(2, 1, 7);
console.log(arr); // [1, 6, 7, 4, 5]
// 插入和删除元素
arr.unshift(0);
console.log(arr); // [0, 1, 6, 7, 4, 5]
arr.push(8);
console.log(arr); // [0, 1, 6, 7, 4, 5, 8]
arr.splice(3, 0, 9);
console.log(arr); // [0, 1, 6, 9, 7, 4, 5, 8]
arr.pop();
console.log(arr); // [0, 1, 6, 9, 7, 4, 5]
arr.shift();
console.log(arr); // [1, 6, 9, 7, 4, 5]
arr.splice(2, 1);
console.log(arr); // [1, 6, 7, 4, 5]
// 其他操作
arr.sort();
console.log(arr); // [1, 4, 5, 6, 7]
arr.reverse();
console.log(arr); // [7, 6, 5, 4, 1]
var newArr = arr.concat([2, 3]);
console.log(newArr); // [7, 6, 5, 4, 1, 2, 3]
var str = arr.join('-');
console.log(str); // "7-6-5-4-1"
arr.fill(0);
console.log(arr); // [0, 0, 0, 0, 0]
</script>
</body>
</html>
优势与劣势
- 优势:快速随机访问、高效的查找(如二分查找)
- 劣势:插入和删除操作影响性能,需要移动大量元素
适用场景
数组适用于读取操作多、写操作少的情况。
持续学习总结记录中,回顾一下上面的内容:
创建数组
Array 构造函数:new Array() 或 new Array(1, 2, 3),需要 new 关键字
方括号 []:[] 或 [1, 2, 3],更简洁
判断、长度和遍历数组
Array.isArray(arr):判断是否是数组
arr.length:获取数组长度
遍历方式:for、forEach、map、filter、some、every、find
基本操作
读取/查找:arr[index]、indexOf、lastIndexOf
更新/替换:直接赋值或使用 splice()
插入和删除元素
插入:unshift()(首部)、push()(尾部)、splice()(中间)
删除:pop()(尾部)、shift()(首部)、splice()(中间)
其他操作
排序和反序:sort()、reverse()
连接:concat()
转换为字符串:join()、toString()