数组
与变量相比 变量只能储存一个值
数组的作用:数组可以储存很多值,一组数据的集合储存在单个变量下的优雅方式(Array)
var arr = [123,50,60,70,]; // 常用
var arr1 = []; 创建了一个空数组
字面量创建数组 字面量 一种固定值的表示方法
var arr =new Array();
利用new (创建数组)
var arr2 = [1,3,'pink老师',true];
数组里面的数据一定用逗号分隔
数组里面的数据 称为 数组元素
声明数组并赋值称为数组的初始化
数组里面的数据可以是任意类型的
// 数组的长度是元素的个数 不要跟索引号混淆
// arr.length 动态检测数组元素的个数
/* 求数组的最大值
1.准备一个容器
2.遍历数组
3.每一个元素都和sum比较
4.每次大于sum都放入sum里面
5.直到不大于sum为止然后打印它
*/
arr = [10, 20, 99, 37, 51,]
// 方法一
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] > sum) {
sum = arr[i];
}
}
console.log(sum);
// 方法二
var sum = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] > sum) {
sum = arr[i];
}
}
console.log(sum);
//算法: 冒泡排序
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log(arr);
for (var j = 0; j < arr.length - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
console.log(arr);
for (var j = 0; j < arr.length - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
console.log(arr);
// 外层循环决定执行多少次
for (var i = 0; i < arr.length; i++) {
// 冒泡排序的核心代码
for (var j = 0; j < arr.length - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);//[1, 2, 3, 4, 5, 6, 7, 8, 9]
// //第一次循环
arr1 = [9, 8, 7, 6, 5, 4, 3, 2, 1,];
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr1.length - 1; j++) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
console.log(arr);//[1, 2, 3, 4, 5, 6, 7, 8, 9]
冒泡排序及其多种优化方法
算法
- 解决某一个问题, 性能相对更好的哪一个解决方案
小案例
- 需求: 对比数组前一项与他的后一项, 如果前一项的值大于后一项的, 那么将前后两项交换位置
1.for循环遍历数组
2.对比数组前一项与他的后一项,如果前一项的值大于后一项的(if分支)
3.前后两项交换位置 (引入第三个变量)
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log('原数组:',arr);[9, 8, 7, 6, 5, 4, 3, 2, 1]
// 算法 : 冒泡排序 (未优化)
for (var k = 0; k < arr.length; k++) {
// k的范围为 0~8
for (var i = 0; i < arr.length; i++) {
// i的范围为 0~8
if (arr[i] > arr[i + 1]) {
var tem = arr[i] // 存储最开始 [0] 的值
arr[i] = arr[i + 1]
arr[i + 1] = tem // 需要使用 最开始 [0] 的值
}
}
}
console.log(arr); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
步骤解析:
// k ==1 2次循环 i ==1
if (arr[1] > arr[2]) {
var tem = arr[1]
arr[1] = arr[2]
arr[2] = tem
}// k ==2 3次循环 i ==2
if (arr[2] > arr[3]) {
var tem = arr[2]
arr[2] = arr[3]
arr[3] = tem
}// k ==3 4次循环 i ==3
if (arr[3] > arr[4]) {
var tem = arr[3]
arr[3] = arr[4]
arr[4] = tem
}
// k ==4 5次循环 i ==4
if (arr[4] > arr[5]) {
var tem = arr[4]
arr[4] = arr[5]
arr[5] = tem
}
// k ==5 6次循环 i ==5
if (arr[5] > arr[6]) {
var tem = arr[5]
arr[5] = arr[6]
arr[6] = tem
}// k ==6 7次循环 i ==6
if (arr[6] > arr[7]) {
var tem = arr[6]
arr[6] = arr[7]
arr[7] = tem
}
// k ==7 8次循环 i ==7
if (arr[7] > arr[8]) {
var tem = arr[7]
arr[7] = arr[8]
arr[8] = tem
}
// k ==8 9次循环 i ==8
if (arr[8] > arr[9]) {
var tem = arr[8]
arr[8] = arr[9]
arr[9] = tem
}
//因为最后一次
if(arr[8] > arr[9]) {
var tem = arr[8]
arr[8] = arr[9]
arr[9] = tem
}
// i 超过 数组的长度 没有意义
- 优化方案
// 优化一
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1];
// 下标 0 1 2 3 4 5 6 7 8 length: 9
console.log('原素组:', arr);
for (var k = 0; k < arr.length - 1; k++) {
// 外部循环决定内部循环的次数 0~8
for (var i = 0; i < arr.length - 1; i++) {
// 遍历数组
if (arr[i] > arr[i + 1]) {
// 对比数组前一项与他的后一项,如果前一项的值大于后一项的(if分支)
var temp = arr[i]; // 储存最开始[0]的值
arr[i] = arr[i + 1];
arr[i + 1] = temp; // 需要使用最开始[0]的值
// 前后两项交换位置
}
}
}
console.log(arr);
步骤解析:
第 1 次循环确定了 [8] [8, 7, 6, 5, 4, 3, 2, 1, 9]
第 2 次循环确定了 [7][8] [7, 6, 5, 4, 3, 2, 1, 8, 9]
第 3 次循环确定了 [6][7][8] [6, 5, 4, 3, 2, 1, 7, 8, 9]
第 4 次循环确定了 [5][6][7][8] [5, 4, 3, 2, 1, 6, 7, 8, 9]
第 5 次循环确定了 [4][5][6][7][8] [4, 3, 2, 1, 5, 6, 7, 8, 9]
第 6 次循环确定了 [3][4][5][6][7][8] [3, 2, 1, 4, 5, 6, 7, 8, 9]
第 7 次循环确定了 [2][3][4][5][6][7][8] [2, 1, 3, 4, 5, 6, 7, 8, 9]
第 8 次循环确定了 [1][2][3][4][5][6][7][8] [1, 2, 3, 4, 5, 6, 7, 8, 9]
第 9 次循环确定了 [1][2][3][4][5][6][7][8] [1, 2, 3, 4, 5, 6, 7, 8, 9]
分析之后发现, 最后一轮外层循环是没有意义的, 所以我们可以减少最后一次循环
也就是说, 外层循环的结束条件应该调整为 k < arr.length - 1
// 个人书写的代码
// 循环次数 (i) 遍历次数
// k ==0 1 0 1
for (var i = 0; i < arr.length - 1; i++) {
if (arr[0] > arr[1]) {
var temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
}
k ==1 2 1 2
for (var i = 1; i < arr.length - 1; i++) {
if (arr[1] > arr[2]) {
var temp = arr[1];
arr[1] = arr[2];
arr[2] = temp;
}
}
// ...7 8 7 8
// k < arr.length - 1 arr.length - 1 < arr.length - 1 arr.length - 1
- 优化二
var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7]
// 下标 0 1 2 3 4 5 6 7 8 length: 9
console.log('原数组', arr)
// // 优化1
for (var k = 0; k < arr.length; k++) { // 决定内部的 冒泡排序执行多少次
内循环: 冒泡排序的核心代码
/**
*
* for (var i = 0; i < arr.length-1; i++) {
* 当前 i 的值为 0~8
*
* 如果最后一轮循环的时候, i === 8
* 分支语句: if (arr[i] > arr[i + 1]) -> if (arr[8] > arr[9])
* 因为没有 下标9 的项, 所以当前循环最后一轮是没有意义的, 我们应该减少最一轮循环
* 所以循环的结束条件应该修改为 i < arr.length - 1
*/
for (var i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
var tem = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tem
}
}
}
console.log(arr);
// 优化三
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1]
// 下标 0 1 2 3 4 5 6 7 8 length: 9
// console.log('原数组', arr)
/**
* 经过这个打印之后, 我们发现, 每一轮循环, 都有一些没有必要的判断
* 规律是: 每一轮判断的执行次数, 减少 k 次
*
* 因为 内部的 if 判断, 是由内循环决定次数的, 所以我们在 内循环的执行次数上, 加上一个 - k
*
* 所以最后的 内循环结束条件: i < arr.length - 1 - k
*/
for (var k = 0; k < arr.length - 1; k++) {
// 决定内部的 冒泡排序执行多少次
// 内循环: 冒泡排序的核心代码
// console.log('当前是第', k + 1, '次', '当前k==', k);
for (var i = 0; i < arr.length; i++) {
// i 0~7 8次
if (arr[i] > arr[i + 1]) {
var temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
// console.log('=============================');
}
console.log(arr);
//步骤解析
// k 循环次数 i 遍历次数
// 0 1 0 1
if (arr[0] > arr[1]) {
var temp = arr[0]; //[8, 7, 6, 5, 4, 3, 2, 1, 9]
arr[0] = arr[1];
arr[1] = temp;
}
// 1 2 1 2
if (arr[1] > arr[2]) {
var temp = arr[1]; //[7, 6, 5, 4, 3, 2, 1, 8, 9]
arr[1] = arr[2];
arr[2] = temp;
}
// 2 3 2 3
if (arr[2] > arr[3]) {
var temp = arr[2]; //[6, 5, 4, 3, 2, 1, 7, 8, 9]
arr[2] = arr[3];
arr[3] = temp;
}
//...
// 7 8 7 8
if (arr[7] > arr[8]) {
var temp = arr[8]; //[1, 2, 3, 4, 5, 6, 7, 8, 9]
arr[7] = arr[8];
arr[8] = temp;
}
// 8 9 8 9
if (arr[8] > arr[9]) {
var temp = arr[9]; //[1, 2, 3, 4, 5, 6, 7, 9, 9]
arr[8] = arr[9];
arr[9] = temp;
}
// 没有任何意义 k 的值为 8 和 k 的值为 7 是一样的没有意义
选择排序
小案例
- 找到最小值
var arr = [2, 6, 3, 1, 9, 5, 8, 7, 4];
// 索引为 0 1 2 3 4 5 6 7 8
console.log(arr);
for (var k = 0; k < arr.length; k++) {
// 创建一个变量,储存当前假设的最小值的下标
}
var sum = 0;
for (var i = 1; i < arr.length; i++) {
if (arr[sum] > arr[i]) {
sum = i;
}
}
console.log(sum);// 最小值的索引为3
var temp = arr[0];
// 把真实的最小值给第三个变量
arr[0] = arr[sum];
// 把求出的最小值即真实最小值赋值给arr[0]
// 即真实最小值位置编程了第一个位置
arr[sum] = temp;
// 换过来的值换到原来真实最小值的位置
console.log(arr);
- 优化二
步骤分析:
//第几次循环 // sum (假设真实数) 与数组的元素(i)进行比较 真实最小值的索引
// k ===0 1 0 1 0
// k ===1 2 1 2 1
// k ===2 3 2 3 2
for (var k = 0; k < arr.length; k++) {
var sum = k;
for (var i = k + 1; i < arr.length; i++) {
if (arr[sum] > arr[k+1]) {
sum = k+1;
}
}
var temp = arr[k];
arr[k] = arr[sum];
arr[sum] = arr[temp];
}
console.log(arr);
步骤解析:
var sum = 0;
for (var i = 1; i < arr.length; i++) {
if (arr[sum] > arr[i]) {
sum = i;
}
}
var temp = arr[i];
arr[i] = arr[sum]
arr[sum] = temp;
console.log('选择排序后: ', arr);
var sum = 1;
for (var i = 2; i < arr.length; i++) {
if (arr[1] > arr[2]) {
sum = 2;
}
}
var temp = arr[2];
arr[2] = arr[1]
arr[1] = temp;
console.log('选择排序后: ', arr);
var sum = 2;
for (var i = 3; i < arr.length; i++) {
if (arr[2] > arr[3]) {
sum = 3;
}
}
var temp = arr[3];
arr[3] = arr[2]
arr[2] = temp;
console.log('选择排序后: ', arr);
步骤解析二
var sum = 1;
for (var i = 2; i < arr.length; i++) {
if (arr[sum] > arr[i]) {
sum = i;
}
}
console.log(sum);// 最小值的索引为3
var temp = arr[1];
// 把真实的最小值给第三个变量
arr[1] = arr[sum];
// 把求出的最小值即真实最小值赋值给arr[0]
// 即真实最小值位置编程了第一个位置
arr[sum] = temp;
// 换过来的值换到原来真实最小值的位置
1;
var sum = 2;
for (var i = 3; i < arr.length; i++) {
if (arr[sum] > arr[i]) {
sum = i;
}
}
console.log(sum);// 最小值的索引为3
var temp = arr[2];
// 把真实的最小值给第三个变量
arr[2] = arr[sum];
// 把求出的最小值即真实最小值赋值给arr[0]
// 即真实最小值位置编程了第一个位置
arr[sum] = temp;
// 换过来的值换到原来真实最小值的位置
数据类型之间的区别
- 基本数据类型
- 复杂数据类型
存储的区别
1.基本数据类型(string, numbe, undefined, null, boolean)
会直接将数据类型存储到 栈内存中
2.复杂数据类型(object, array, function)
将数据本体, 存放在堆内存中, 然后将指向堆内存的地址,
存储在 变量名中, 最后变量名存储在 栈内存中
比较的区别
1.基本数据类型
- 直接将数据进行对比 2.复杂数据类型
- 因为变量内部存储的是 一个地址, 所以对比时, 对比的是地址, 而不是真正的值
代码解析:
var arr = [1,2,3,4,5,];
var arr1 = [1,2,3,4,5,];
console.log(arr===arr1);// false
赋值的区别
1.基本数据类型
直接将数据类型给另一个变量;赋值完成之后, 两个变量没有任何关系
类似于, 我有一张考试卷子, 我复制出来一份给你, 然后你对你的卷子有任何修改, 都不会影响我这一张卷子
2.复杂数据类型
因为复杂数据类型的变量名中 存储的是指向一个堆内存的地址, 所以在做赋值的时候, 是把这个地址赋值给另一个变量了,所以修改另外一个变量的时候, 会影响自身
类似于: 我有一个房间的钥匙, 然后我将钥匙复制一份, 给你一个, 你后续能够进入这个房间了, 后续如果你对这个房间做了任何修改在我进入房间的时候, 我都能看到
var arr = 100;
var num = arr; // 直接将 arr 内部的数据赋值给另一个变量, 也就是 num
num++;
console.log(num,arr);//101 100
var arr =[1,2,3]
var newArr = arr
newArr[0] = 100
console.log(arr) // [100,2,3]
传参的区别
1.基本数据类型
- 将数据拷贝一份传递给形参, 在函数内对形参的修改并不会影响外界
- 复杂数据类型
- 将变量内部存储的地址, 赋值给形参, 也就是说, 函数内部的形参, 和外部的变量, 共同享用同一个地址所以在函数内对形参的修改会影响外界
代码解析:
function fn(str){
str ='QF001'
console.log('str:', str) //QF001
}
var winStr ='qwer'
fn(winStr)
console.log('winStr:', winStr) //qwer
小案例(1):
function fn2(arr){
arr[0]=100
console.log('arr:', arr) //[100,2,3]
// 实际上是 arr =winArr 即 [1,2,3]
// 利用复杂数据类型的传参区别 arr 的地址和 winArr相同
// 所以 arr = [100,2,3]
}
var winArr =[1,2,3];
fn2(winArr)
console.log('winArr:',winArr)//[100,2,3]
小案例(2):
var obj = {
name: 'QF001'
}
function fn(obj) {
// 相当于obj.name = 'QF001'
// 利用复杂数据类型的传参区别 全局变量的name:'QF002'
obj.name = 'QF002'
obj = {}
// 将一个空对相想赋值给变量obj
// 并且在当前作用域内找 obj.name = 'QF002'
obj.name = 'QF003'
console.log(obj.name);//QF003
}
fn(obj);
console.log(obj.name);// QF002
数组的常用方法
1. push()
语法: 数组.push()
作用: 将这个 "数据", 追加到数组的末尾, 向数组末尾, 添加新数据
返回值: 追加新数据后, 数组的最新的长度 length
2.pop()
语法: 数组.pop()
作用: 删除数组的最后一项
返回值: 删除的哪一项对应的值
3.unshift()
语法: 数组.unshift(数据)
作用: 将这个 "数据", 添加到数组的开头
返回值: 追加新数据后, 数组的最新长度 length
4.shift()
语法: 数组.shift()
作用: 删除数组的第一项
返回值: 删除的哪一项对应的值
5.reverse()
语法: 数组.reverse()
作用: 反转数组
返回值: 反转后的数组
上述方法, 都能够改变原数组
代码演示:
//1. push
var arr = [1, 2, 3]
var ars = arr.push(4); // 将 数字 4, 追加到数组的末尾, 并将数组最新的长度, 赋值给变量 res
arr.push(5) // 将数字 5, 追加到数组的末尾(这种写法更为常见)
console.log(arr); // [1, 2, 3,4]
2.pop();
var arr = [1, 2, 3];
var res = arr.pop();
arr.pop();
console.log(res);//3
console.log(arr);//[1]
// 3.unshift
var arr = [1, 2, 3];
var res = arr.unshift(0);
console.log(res);// 4
console.log(arr);// [0,1,2,3,]
// 4.shift
var arr = [1, 2, 3]
var res = arr.shift()
console.log(res) // 1
console.log(arr) // [2, 3]
// 5. reverse
var arr = [1, 2, 3]
var res = arr.reverse()
console.log('res', res) // [3,2,1]
console.log('arr', arr)//[3,2,1]
```