JavaScript数据结构与算法学习

 

本文只是简单的记录JavaScript学习笔记,由于有一定的基础所以只记录常用的不熟悉的技术点,感谢理解

第一章:

 

第二章:数组:

数组的标准定义是: 一个存储元素的线性集合( collection), 元素可以通过索引来任意存
取, 索引通常是数字, 用来计算元素之间存储位置的偏移量。 几乎所有的编程语言都有类
似的数据结构。 然而 JavaScript 的数组却略有不同。
JavaScript 中的数组是一种特殊的对象, 用来表示偏移量的索引是该对象的属性, 索引可
能是整数。 然而, 这些数字索引在内部被转换为字符串类型, 这是因为 JavaScript 对象中
的属性名必须是字符串。 数组在 JavaScript 中只是一种特殊的对象, 所以效率上不如其他
语言中的数组高。

JavaScript 中的数组, 严格来说应该称作对象, 是特殊的 JavaScript 对象, 在内部被归类为数
组。 由于 Array 在 JavaScript 中被当作对象, 因此它有许多属性和方法可以在编程时使用。

1.数组的简单创建

var arr = [];

var arr = new Array();

var objects = [1, "Joe", true, null];

可以调用 Array.isArray() 来判断一个对象是否是数组, 如下所示:

var numbers = 3;
var arr = [7,4,1776];
console.log(Array.isArray(numbers)); // 显示 false
console.log(Array.isArray(arr)); // 显示 true

 

2.数组操作的最重要两个函数:

slice() 方法可从已有的数组中返回选定的元素。

arrayObject.slice(start,end)

参数描述
start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

 

var color = new Array('red', 'blue', 'yellow', 'black');
var color2 = color.slice(1, 2);
console.log(color2); //只输出:blue

 

在javascript中splice()方法,是一个很强的数组方法,它有多种用法。
splice()主要用途是向数组的中部插入项。

有如下3种方式:
删除——可以删除任意数量的项,只需要指定2个参数:要删除的第一项的位置和要删除项的项数。
例如,splice(0,2)会删除数组中的前两项。
插入——可以向指定位置插入任意数量的项,只需要提供3个参数:骑士位置、0(要删除的项数)和要插入的项。
如果要插入多个项,可以再传入第四、第五,一直任意多个项。
例如,splice(2,1,”red”,”green”)会删除当前数组位置2的项,然后再从位置2开始插入字符串“red”和”green”。

var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1);  //删除第一项
alert(colors);  //green,blue
alert(removed);  //red,返回数组中值包含一项

removed = colors.splice(1, 0, "yellow", "orange");  //从位置1开始插入两项
alert(colors);  //green,yellow,organge,blue
alert(removed);  //返回的是一个空数组

removed = colors.splice(1, 1, "red", "purple");  //插入两项,删除一项
alert(colors);  //green,red,purple,orange,blue
alert(remove);  //yellow, 返回的数组中只包含一项

 

使用 pop() 方法可以删除数组末尾的元素:
var nums = [1,2,3,4,5,9];
nums.pop();
print(nums); // 1,2,3,4,5

 

unshift() 方法可以将元素添加在数组的开头, 下述代码展示了该方法的用法:
var nums = [2,3,4,5];
print(nums); // 2,3,4,5
var newnum = 1;
nums.unshift(newnum);
print(nums); // 1,2,3,4,5
nums = [3,4,5];
nums.unshift(newnum,1,2);
print(nums); // 1,2,3,4,5
第二次出现的 unshift() 方法展示了可以通过一次调用, 为数组添加多个元素。

unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。

栈数据结构的访问规则是LIFO(后进先出),而队列数据结构的访问规则是FIFO(first-in-first-out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。由于push()是向数组末端添加项的方法,一次要模拟队列只需一个从数组前端取得项的方法。实现这以一操作的数组方法就是shift(),它能够移除数组中的第一项并返回该项,同时将数组长度减1。结合使用shift()和push()方法,可以像使用队列一样使用数组:

 

var colors = new Array();                 //创建一个数组
var count = colors.push("red", "green");  //推入两项
alert(count);                             //2
count = colors.push("black");             //推入另一项
alert(count);                             //3
var item = colors.shift();                //取得第一项
alert(item);                              //"red"
alert(colors.length);                     //2

ECMAScript还为数组提供了一个unshift()方法。unshift()shift()的用途相反:它能在数组的前端添加任意各项并返回新数组的长度。因此,同时使用unshift()和pop()方法,可以从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项,如下面的例子所示:

var colors = new Array();                    //创建一个数组
var count = colors.unshift("red", "green");  //推入两项
alert(count);                                //2

count = colors.unshift("black");             //推入另一项
alert(count);

var item = colors.pop();                     //取得最后一项
alert(item);                                 //"green"
alert(colors.length);                        //2

IE对JavaScript的实现存在一个偏差,其unshift()方法总是返回undefined而不是数组的新长度。

2.4.4 为数组排序

剩下的两个可变方法是为数组排序。 第一个方法是 reverse(), 该方法将数组中元素的顺
序进行翻转。 下面这个例子展示了该如何使用该方法:
var nums = [1,2,3,4,5];
nums.reverse();
print(nums); // 5,4,3,2,1

 

对数组进行排序是经常会遇到的需求, 如果元素是字符串类型, 那么数组的可变方法
sort() 就非常好使:
var names = ["David","Mike","Cynthia","Clayton","Bryan","Raymond"];
names.sort();
print(names); // Bryan,Clayton,Cynthia,David,Mike,Raymond

 

但是如果数组元素是数字类型, sort() 方法的排序结果就不能让人满意了:
var nums = [3,1,2,100,4,200];
nums.sort();
print(nums); // 1,100,2,200,3,4
sort() 方法是按照字典顺序对元素进行排序的, 因此它假定元素都是字符串类型, 在上一
个例子中, 即使元素是数字类型, 也被认为是字符串类型。 为了让 sort() 方法也能排序数
字类型的元素, 可以在调用方法时传入一个大小比较函数, 排序时, sort() 方法将会根据
该函数比较数组中两个元素的大小, 从而决定整个数组的顺序。
对于数字类型, 该函数可以是一个简单的相减操作, 从一个数字中减去另外一个数字。 如
果结果为负, 那么被减数小于减数; 如果结果为 0, 那么被减数与减数相等; 如果结果为
正, 那么被减数大于减数。
将这些搞清楚之后, 传入一个大小比较函数, 再来看看前面的例子:
function compare(num1, num2) {
return num1 - num2;
} v
ar nums = [3,1,2,100,4,200];
nums.sort(compare);
print(nums); // 1,2,3,4,100,200
sort() 函数使用了 compare() 函数对数组按照数字大小进行排序, 而不是按照字典顺序

 

这组中的第一个方法是 forEach(), 该方法接受一个函数作为参数, 对数组中的每个元素
使用该函数。 下面这个例子展示了如何使用该方法:
function square(num) {
print(num, num * num);
} v
ar nums = [1,2,3,4,5,6,7,8,9,10];
nums.forEach(square);
数组 | 23
该程序的输出为:
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100

 

另一个迭代器方法是 every(), 该方法接受一个返回值为布尔类型的函数, 对数组中的每
个元素使用该函数。 如果对于所有的元素, 该函数均返回 true, 则该方法返回 true。 下面
是一个例子:
function isEven(num) {
return num % 2 == 0;
} v
ar nums = [2,4,6,8,10];
var even = nums.every(isEven);
if (even) {
print("all numbers are even");
} e
lse {
print("not all numbers are even");
}
输出为:
all numbers are even
将数组改为:
var nums = [2,4,6,7,8,10];
输出为:
not all numbers are even

 

some() 方法也接受一个返回值为布尔类型的函数, 只要有一个元素使得该函数返回 true,
该方法就返回 true。 比如:
function isEven(num) {
return num % 2 == 0;
} v
ar nums = [1,2,3,4,5,6,7,8,9,10];
var someEven = nums.some(isEven);
24 | 第 2 章
if (someEven) {
print("some numbers are even");
} e
lse {
print("no numbers are even");
} n
ums = [1,3,5,7,9];
someEven = nums.some(isEven);
if (someEven) {
print("some numbers are even");
} e
lse {
print("no numbers are even");
}
该程序的输出为:
some numbers are even
no numbers are even

 

reduce() 方法接受一个函数, 返回一个值。 该方法会从一个累加值开始, 不断对累加值和
数组中的后续元素调用该函数, 直到数组中的最后一个元素, 最后返回得到的累加值。 下
面这个例子展示了如何使用 reduce() 方法为数组中的元素求和:
function add(runningTotal, currentValue) {
return runningTotal + currentValue;
} v
ar nums = [1,2,3,4,5,6,7,8,9,10];
var sum = nums.reduce(add);
print(sum); // 显示 55
reduce() 方法和 add() 函数一起, 从左到右, 依次对数组中的元素求和, 其执行过程如下
所示:
add(1,2) -> 3
add(3,3) -> 6
add(6,4) -> 10
add(10,5) -> 15
add(15,6) -> 21
add(21,7) -> 28
add(28,8) -> 36
add(36,9) -> 45
add(45,10) -> 55
reduce() 方法也可以用来将数组中的元素连接成一个长的字符串:
function concat(accumulatedString, item) {
return accumulatedString + item;
} v
ar words = ["the ", "quick ","brown ", "fox "];
数组 | 25
var sentence = words.reduce(concat);
print(sentence); // 显示 "the quick brown fox"
JavaScript 还提供了 reduceRight() 方法, 和 reduce() 方法不同, 它是从右到左执行。 下面
的程序使用 reduceRight() 方法将数组中的元素进行翻转:
function concat(accumulatedString, item) {
return accumulatedString + item;
} v
ar words = ["the ", "quick ","brown ", "fox "];
var sentence = words.reduceRight(concat);
print(sentence); // 显示 "fox brown quick the"

 

2.5.2 生成新数组的迭代器方法
有两个迭代器方法可以产生新数组: map() 和 filter()。 map() 和 forEach() 有点儿像, 对
数组中的每个元素使用某个函数。 两者的区别是 map() 返回一个新的数组, 该数组的元素
是对原有元素应用某个函数得到的结果。 下面给出一个例子:
function curve(grade) {
return grade += 5;
} v
ar grades = [77, 65, 81, 92, 83];
var newgrades = grades.map(curve);
print(newgrades); // 82, 70, 86, 97, 88
下面是对一个字符串数组使用 map() 方法的例子:
function first(word) {
return word[0];
} v
ar words = ["for","your","information"];
var acronym = words.map(first);
print(acronym.join("")); // 显示 "fyi"
在上面这个例子中, 数组 acronym 保存了数组 words 中每个元素的第一个字母。 然而, 如
果想将数组显示为真正的缩略形式, 必须想办法除掉连接每个数组元素的逗号, 如果直接
调用 toString() 方法, 就会显示出这个逗号。 使用 join() 方法, 为其传入一个空字符串
作为参数, 则可以帮助我们解决这个问题。
filter() 和 every() 类似, 传入一个返回值为布尔类型的函数。 和 every() 方法不同的是,
当对数组中的所有元素应用该函数, 结果均为 true 时, 该方法并不返回 true, 而是返回
一个新数组, 该数组包含应用该函数后结果为 true 的元素。 下面是一个例子:
function isEven(num) {
26 | 第 2 章
return num % 2 == 0;
} f
unction isOdd(num) {
return num % 2 != 0;
} v
ar nums = [];
for (var i = 0; i < 20; ++i) {
nums[i] = i+1;
} v
ar evens = nums.filter(isEven);
print("Even numbers: ");
print(evens);
var odds = nums.filter(isOdd);
print("Odd numbers: ");
print(odds);
该程序的执行结果如下:
Even numbers:
2,4,6,8,10,12,14,16,18,20
Odd numbers:
1
,3,5,7,9,11,13,15,17,19
下面是另一个使用 filter() 方法的有趣案例:
function passing(num) {
return num >= 60;
} v
ar grades = [];
for (var i = 0; i < 20; ++i) {
grades[i] = Math.floor(Math.random() * 101);
} v
ar passGrades = grades.filter(passing);
print("All grades: );
print(grades);
print("Passing grades: ");
print(passGrades);
程序显示:
All grades:
39,43,89,19,46,54,48,5,13,31,27,95,62,64,35,75,79,88,73,74
Passing grades:
89,95,62,64,75,79,88,73,74
当然, 还可以使用 filter() 方法过滤字符串数组, 下面这个例子过滤掉了那些不包含
“ cie” 的单词:
function afterc(str) {
数组 | 27
if (str.indexOf("cie") > -1) {
return true;
} r
eturn false;
} v
ar words = ["recieve","deceive","percieve","deceit","concieve"];
var misspelled = words.filter(afterc);
print(misspelled); // 显示 recieve,percieve,concieve

posted @ 2015-10-29 17:22  wfpanskxin  阅读(158)  评论(0)    收藏  举报