學習JavaScript數據結構與算法(數組)

數組

數組是最簡單的內存數據結構,存儲一系列同一種類型的值。雖然在JavaScript裏,也能夠在數組中保存不一樣類型的值,但咱們仍是遵照最佳實踐,避免這麼作(大多數語言都沒這個能力)。面試

1.建立和初始化數組

// new關鍵字方式
let daysOfWeek = new Array(); 
daysOfWeek = new Array(7);
daysOfWeek = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');

// 字面量方式
let daysOfWeek = [];
let daysOfWeek = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

console.log(daysOfWeek.length); // 7
複製代碼

訪問元素和迭代數組

// 經過循環迭代數組、打印元素
for(let i = 0; i < daysOfWeek.length; i++) {
    console.log(daysOfWeek[i]);
}
複製代碼

求斐波那契數列的前20個數。已知斐波那契數列中的前兩項是1,從第三項開始,每一項都等於前兩項之和。算法

const fibonacci = [];
fibonacci[1] = 1;
fibonacci[2] = 1;

for(let i = 3; i < 20; i++) {
    fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];
}

for(let i = 1; i < fibonacci.length; i++) {
    console.log(fibonacci[i])
}
複製代碼

2.添加元素

假如咱們有一個數組numbers,初始化成了0到9。數組

let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8,  9];
複製代碼

2.1 在數組末尾插入元素

numbers[numbers.length] = 10;
複製代碼

使用push方法

numbers.push(11);
numbers.push(12,13);
複製代碼

2.2 在數組開頭插入元素

首先要騰出數組裏第一個元素的位置,把全部元素向右移動一位。咱們能夠循環數組中的元素,從最後一位(長度值就是數組的末尾位置)開始,將對應的前一個元素(i-1)的值賦值給它(i),依次處理,最後把咱們想要的值賦值給第一個位置(索引0)上。bash

Array.prototype.insertFirstPosition = function (value) {
    for(let i = this.length; i >= 0; i--) {
        this[i] = this[i-1];
    }
    this[0] = value;
}

numbers.insertFirstPosition(-1)
複製代碼

使用unshift方法

unshift方法背後的邏輯和insertFirstPosition方法的行爲是同樣的。數據結構

numbers.unshift(-2);
numbers.unshift(-4,-3);
複製代碼

3.刪除元素

3.1 從數組末尾刪除元素

numbers.pop();
複製代碼

3.1 從數組開頭刪除元素

Array.prototype.reIndex = function(myArray) {
    const newArray = [];
    for(let i = 0; i < myArray.length; i++) {
        if(myArray[i] !== undefined) {
            newArray.push(myArray[i]);
        }
    }
    return newArray
}

Array.prototype.removeFirstPosition = function() {
    for(let i = 0; i < this.length; i++) {
        this[i] = this[i+1];
    }
    return this.reIndex(this);
}

numbers = numbers.removeFirstPosition();
複製代碼

使用shift方法

numbers.shift();
複製代碼

4.在任意位置添加或刪除元素

// 刪除從數組索引5開始的3個元素
numbers.splice(5,3); 
// 把數二、三、4插入數組裏,放到以前刪除元素的位置上
numbers.splice(5,0,2,3,4);
// 從索引5開始刪除了3個元素,但也從索引5開始添加了元素二、三、4
numbers.splice(5,3,2,3,4);
複製代碼

5.二維和多維數組

let averageTemp = [];
averageTemp[0] = [1,2,3,4];
averageTemp[1] = [5,6,7,8];

複製代碼

5.1 迭代二維數組的元素

function printMatrix(myMatrix) {
    for(let i = 0; i < myMatrix.length; i++) {
        for(let j = 0; j < myMatrix[i].length; j++) {
            console.log(myMatrix[i][j])
        }
    }
}
複製代碼

5.2 多維數組

假設咱們要建立一個3x3x3的矩陣,每一格里包含矩陣的i(行)、j(列)及z深度之和。函數

const matrix3x3x3 = [];
for(let i = 0; i < 3; i++) {
    matrix3x3x3[i] = [];
    for(let j = 0; j < 3; j++) {
        matrix3x3x3[i][j] = [];
        for(let z = 0; z < 3; z++) {
            matrix3x3x3[i][j][z] = i+j+z;
        }
    }
}
複製代碼

用如下代碼輸出這個矩陣的內容ui

for(let i = 0; i < matrix3x3x3.length; i++) {
    for(let j = 0; j < matrix3x3x3[i].length; j++) {
        for(let z = 0; z < matrix3x3x3[i][j].length; z++) {
            console.log(matrix3x3x3[i][j][z])
        }
    }
}
複製代碼

6.JavaScript的數組方法參考

6.1 數組合並

const zero = 0;
const positiveNumbers = [1,2,3];
const negativeNumbers = [-3,-2,-1];
let numbers = negativeNumbers.concat(zero,positiveNumbers); // [-3,-2,-1,0,1,2,3]
複製代碼

6.2 迭代器函數

假設數組中的值是從1到15;若是數組裏的元素能夠被2整除(偶數),函數就返回true,不然就返回false。this

function isEven(x) {
    // 若是x是2的倍數,就返回true
    console.log(x);
    return x % 2 === 0;
}
// 使用箭頭函數改寫isEven函數
const isEven = x => x % 2 === 0;

let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

複製代碼
  • 1.用every方法迭代 every方法會迭代數組中的每一個元素,直到返回false。
numbers.every(isEven);
複製代碼

數組numbers的第一個元素是1,它不是2的倍數(1是奇數),所以isEven函數返回false,而後every執行結束。spa

  • 2.用some方法迭代 some方法會迭代數組中的每一個元素,直到返回true。
numbers.some(isEven);
複製代碼

numbers數組中的第一個偶數是2(第二個元素)。第一個被迭代的元素是1,isEven會返回false。第二個被迭代的元素是2,isEven返回true--迭代結束。prototype

  • 3.用forEach方法迭代 它和使用for循環的結果相同
numbers.forEach(x => {
    console.log(x % 2 === 0)
})
複製代碼
  • 4.使用map和filter方法
const myMap = numbers.map(isEven); 
// [false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]

const eventNumbers = numbers.filter(isEven);
// [2,4,6,8,10,12,14]
複製代碼
  • 5.使用reduce方法
numbers.reduce((previous,current) => previous + current);
// 120
複製代碼

6.3 ES6和數組的新功能

  • 1.使用for...of迭代
for(const n of numbers) {
    console.log(n % 2 === 0 ? 'even' : 'odd')
}
複製代碼
  • 2.使用@@iterator對象 ES6爲Array類增長了一個@@iterator屬性,須要經過Symbol.iterator來訪問。
let iterator = numbers[Symbol.iterator]();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3
console.log(iterator.next().value); // 4
console.log(iterator.next().value); // 5
複製代碼

而後不斷調用迭代器的next方法,就能依次獲得數組中的值。

可使用下面代碼來輸出numbers數組中的15個值。

iterator = numbers[Symbol.iterator]();
for(const n of iterator) {
    console.log(n)
}
複製代碼
  • 3.數組的entries、keys和values方法 entries方法返回包含鍵值對的@@iterator。
let aEntries = numbers.entries(); // 獲得鍵值對的迭代器
console.log(aEntries.next().value); // [0,1] - 位置0的值爲1
console.log(aEntries.next().value); // [1,2] - 位置1的值爲2
console.log(aEntries.next().value); // [2,3] - 位置2的值爲3
複製代碼

咱們也可使用下面的代碼。

aEntries = numbers.entries();
for(const n of aEntries) {
    console.log(n);
}
複製代碼

keys方法返回包含數組索引的@@iterator。

const aKeys = numbers.keys(); // 獲得數組索引的迭代器
console.log(aKeys.next()); // {value: 0, done: false}
console.log(aKeys.next()); // {value: 1, done: false}
console.log(aKeys.next()); // {value: 2, done: false}
複製代碼

values方法返回的@@iterator則包含數組的值

const aValues = numbers.values(); 
console.log(aValues.next()); // {value: 1,done: false}
console.log(aValues.next()); // {value: 2,done: false}
console.log(aValues.next()); // {value: 3,done: false}
複製代碼
  • 4.使用from方法 Array.from方法根據已有的數組建立一個新數組。
// 複製numbers數組
let numbers2 = Array.from(numbers);

// 傳入過濾值的函數
let evens = Array.from(numbers,x => (x % 2 == 0))
複製代碼
  • 5.Array.of方法 Array.of方法根據傳入的參數建立一個新數組。
let numbers3 = Array.of(1);
let numbers4 = Array.of(1,2,3,4,5,6);
// 等同於
let numbers3 = [1];
let numbers4 = [1,2,3,4,5,6];
// 複製已有數組
let numbersCopy = Array.of(...numbers);
複製代碼
  • 6.使用fill方法 fill方法用靜態值填充數組。
let numbersCopy = Array.of(1,2,3,4,5,6);

numbersCopy.fill(0);    // [0,0,0,0,0,0]
numbersCopy.fill(2,1);  // [0,2,2,2,2,2]
numbersCopy.fill(1,3,5); // [0,2,2,1,1,2]

let ones = Array(6).fill(1); // [1,1,1,1,1,1]
複製代碼
  • 7.使用copyWithin方法 copyWithin方法複製數組中的一系列元素到同一數組指定的起始位置。
let copyArray = [1,2,3,4,5,6];
copyArray.copyWithin(0,3); // [4,5,6,4,5,6]

copyArray = [1,2,3,4,5,6];
copyArray.copyWithin(1,3,5); // [1,4,5,4,5,6]
複製代碼

6.4 排序元素

let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
// 反序輸出數組numbers
numbers.reverse(); // [15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
numbers.sort();  // [1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9]
複製代碼

sort方法在對數組作排序時,把元素默認成字符串進行相互比較。

咱們能夠傳入本身寫的比較函數。

numbers.sort((a,b) => a-b)
// 等價於
function compare(a,b) {
    if(a < b) {
        return -1;
    }
    if(a > b) {
        return 1;
    }
    return 0;
}
numbers.sort(compare)
複製代碼
  • 1.自定義排序 咱們能夠對任何對象類型的數組排序,也能夠建立compareFunction來比較元素。例如,對象 Person有名字和年齡屬性,咱們但願根據年齡排序。
const friends = [
    { name: 'John', age: 30 },
    { name: 'Ana', age: 20 },
    { name: 'Chris', age: 25 }
]

function comparePerson(a,b) {
    if(a.age < b.age) {
        return -1;
    }
    if(a.age > b.age) {
        return 1;
    }
    return 0;
} 

console.log(friends.sort(comparePerson);
複製代碼
  • 2.字符串排序
let names = ['Ana', 'ana', 'john', 'John'];
console.log(names.sort()); // ["Ana", "John", "ana", "john"]
複製代碼

JavaScript在作字符比較的時候,是根據字符對應的ASCII值來比較的。

let names = ['Ana', 'ana', 'john', 'John'];
console.log(names.sort((a,b) => {
    if(a.toLowerCase() < b.toLowerCase()) {
        return -1;
    }
    if(a.toLowerCase() > b.toLowerCase()) {
        return 1;
    }
    return 0;
}))
// ["Ana", "ana", "john", "John"]
複製代碼

6.5 搜索

搜索有兩個方法:indexOf方法返回與參數匹配的第一個元素的索引;lastIndexOf返回與參數匹配的最後一個元素的索引。

console.log(numbers.indexOf(10)); // 9
console.log(numbers.indexOf(100)); // -1

numbers.push(10);
console.log(numbers.lastIndexOf(10)); // 15
console.log(numbers.lastIndexOf(100)); // -1
複製代碼
  • 1.ES6--find和findIndex方法
let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
function multipleOf13(element,index,array) {
    return (element % 13 == 0);
}

console.log(numbers.find(multipleOf13)); // 13
console.log(numbers.findIndex(multipleOf13)); // 12
複製代碼

find和findIndex的不一樣之處在於,find方法返回第一個知足條件的值,findIndex方法則返回這個值在數組裏的索引。若是沒有知足條件的值,find會返回undefined,而findIndex會返回-1.

  • 2.ES7使用includes方法 若是數組裏存在某個元素,includes方法會返回true,不然返回false
console.log(numbers.includes(15)); // true
console.log(numbers.includes(20)); // false

let numbers2 = [7,6,5,4,3,2,1];
console.log(numbers2.includes(4,5)); // false
複製代碼

6.6 輸出數組爲字符串

let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
console.log(numbers.toString());
// 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

const numberString = numbers.join('-');
console.log(numberString);
// 1-2-3-4-5-6-7-8-9-10-11-12-13-14-15
複製代碼

7.類型數組

類型數組用於存儲單一類型的數據。

let length = 5;
let int16 = new Int16Array(length);

let array16 = [];
array16.length = length;

for(let i = 0; i < length; i++) {
    int16[i] = i + 1;
}
console.log(int16);
複製代碼

8.TypeScript中的數組

TypeScript會在編譯時進行類型檢測,來確保只對全部值都屬於相同數據類型的數組進行操做。

9.小結

數組是最經常使用的數據結構,本節涉及瞭如何聲明和初始化數組、給數組賦值以及添加和刪除數組元素,還有二維、多維數組以及數組的主要方法。這對編寫本身的算法頗有用。

10.經典題目

題目來自《劍指offer》面試題3:二維數組中的查找 在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的二維數組和一個整數,判斷數組中是否含有該整數。

思路:首先選取數組中右上角的數字。若是該數字等於要查找的數字,查找過程結束;若是該數字大於要查找的數字,剔除這個數字所在的列;若是該數字小於要查找的數字,剔除這個數字所在的行。也就是說,若是要查找的數字不在數組的右上角,則每一次都在數組的查找範圍中剔除一行或者一列,這樣每一步均可以縮小查找的範圍,直到找到要查找的數字,或者查找範圍爲空。

var find = function(nums,rows,columns,target) {
        let found = false;
        if(nums !== null && rows > 0 && columns > 0) {
            let row = 0;
            let column = columns -1;
            while(row < rows && column >= 0) {
                console.log(row,column)
                if(nums[row][column] === target) {
                    found = true;
                    break;
                }else if(nums[row][column] > target) {
                    --column;
                }else {
                    ++row;
                }
            }
        }
        console.log(found)
        return found;
    };
    find([[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]],4,4,5)
複製代碼
相關文章
相關標籤/搜索