1.冒泡排序
* 冒泡排序:
* 属于数组排序的算法之一
* 其实就是通过一种算法, 将 一个乱序的数组, 调整为指定顺序的数组(从大到小/从小到大)
*
* 什么是算法?
* 解决某一个问题最简单的方式 / 最高效的方式
*
* 从 1~10万, 这组数字中, 少了一个数字, 要求我们找出来
*
* 常规写法: 后一位 - 前一位 如果 差值 === 2 那么就找出来了
*
* 将 1~10万 分为两组 1~5万 5万零1~10万 然后去找这两组数字中 那一组的数量不够5万, 找到之后将这组再次一分为二
*/
// 准备一个乱序数组
// var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7]
// console.log('原始数组: ', arr)
// 冒泡排序的核心: 对比数组前一项和后一项, 如果前一项的值较大, 那么就往后挪 (这个排序之后是按照从小到大的顺序)
// for (var i = 0; i < arr.length; i++) {
// if (arr[i] > arr[i + 1]) {
// var temp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = temp
// }
// }
// console.log('1 轮冒泡排序后的数组: ', arr)
// 基础版
// for (var k = 0; k < arr.length; k++) { // 决定执行几次 所谓的 冒泡排序
// for (var i = 0; i < arr.length; i++) { // 拿到数组的前一项与后一项, 做一轮排序
// if (arr[i] > arr[i + 1]) {
// var temp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = temp
// }
// }
// }
// console.log('冒泡排序后的数组: ', arr)
/**
* 基础版 有 3 个地方可以优化
*
* 自己优化时: 1. 效果不变 2. 有一个合适的理由
*/
// var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7]
// // 0 1 2 3 4 5 6 7 8
// console.log('原始数组: ', arr)
// // 优化1
// for (var k = 0; k < arr.length; k++) {
// for (var i = 0; i < arr.length - 1; i++) {
// /**
// * i 的值为 0~7, 在最后一次循环的时候, i === 7
// *
// * 判断在执行的时候, 相当于是对比 arr[7] > arr[8]
// *
// * 判断次数少了一次 arr[8] > arr[9]
// */
// if (arr[i] > arr[i + 1]) {
// var temp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = temp
// }
// }
// }
// console.log('冒泡排序后的数组: ', arr)
// var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1]
// // 0 1 2 3 4 5 6 7 8
// console.log('原始数组: ', arr)
// /**
// * 优化2
// *
// * k === 0 第 1 次循环 确定了 [8] 的值
// * k === 1 第 2 次循环 确定了 [7][8] 的值
// * k === 2 第 3 次循环 确定了 [6][7][8] 的值
// * k === 3 第 4 次循环 确定了 [5][6][7][8] 的值
// * k === 4 第 5 次循环 确定了 [4][5][6][7][8] 的值
// * k === 5 第 6 次循环 确定了 [3][4][5][6][7][8] 的值
// * k === 6 第 7 次循环 确定了 [2][3][4][5][6][7][8] 的值
// * k === 7 第 8 次循环 确定了 [1][2][3][4][5][6][7][8] 的值
// * k === 8 第 9 次循环 确定了 [0][1][2][3][4][5][6][7][8] 的值
// *
// * 分析后发现, 外层循环的最后一次 是没有必要, 所以 我们可以将外层循环次数 - 1
// */
// for (var k = 0; k < arr.length - 1; k++) {
// for (var i = 0; i < arr.length - 1; i++) {
// if (arr[i] > arr[i + 1]) {
// var temp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = temp
// }
// }
// }
// console.log('冒泡排序后的数组: ', arr)
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1]
// 0 1 2 3 4 5 6 7 8
console.log('原始数组: ', arr)
/**
* 优化3
*
* 在打印之后, 我们发现 每一轮 循环都有一些没有必要的判断
*
* 规律是: 每一轮判断的执行次数, 减少 k 次
*/
// for (var k = 0; k < arr.length - 1; k++) {
// console.log('这是第', k + 1, '轮循环, 此时 k === ', k)
// for (var i = 0; i < arr.length - 1 - k; i++) {
// console.log(arr[i], arr[i + 1])
// if (arr[i] > arr[i + 1]) {
// var temp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = temp
// }
// }
// console.log(arr)
// }
// console.log('冒泡排序后的数组: ', arr)
// 完整版
for (var k = 0; k < arr.length - 1; k++) {
for (var i = 0; i < arr.length - 1 - k; i++) {
if (arr[i] > arr[i + 1]) {
var temp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = temp
}
}
}
2.选择排序
// var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7]
// // 0 1 2 3 4 5 6 7 8
// console.log('原始数组: ', arr)
// 第一轮选择排序
// var minIndex = 0 // 假设当前最小值的下标 为 0
// for (var i = 1; i < arr.length; i++) {
// if (arr[minIndex] > arr[i]) { // 如果当前分支执行, 说明在数组中找到了一个 比假设的最小值要小的 元素
// minIndex = i
// }
// }
// /**
// * 上边的 for 循环执行完毕后, minIndex 记录的就是 真实的最小的值的下标
// *
// * 此时交换 真实最小值 与 我们假设的最小值
// */
// var temp = arr[0] // 存储 数组下标0的值
// arr[0] = arr[minIndex] // 将 下标0的值重新赋值 当前数组中最小的值
// arr[minIndex] = temp // 将 下标 minIndex 的值 重新赋值为 arr[0] 原本的值 此时就完成了 真实最小值与假设最小值位置的交换
// console.log('第 1 轮选择排序后的数组: ', arr)
// 第二轮选择排序
// var minIndex = 1 // 假设当前最小值的下标为 1
// for (var i = 2; i < arr.length; i++) {
// if (arr[minIndex] > arr[i]) {
// minIndex = i
// }
// }
// // for 循环执行完毕 minIndex 就是真实的最小值的下标, 此时交换 真实最小值与假设的最小值的位置即可
// var temp = arr[1]
// arr[1] = arr[minIndex]
// arr[minIndex] = temp
// console.log('第 2 轮选择排序后的数组: ', arr)
// 第三轮选择排序
// var minIndex = 2 // 假设当前最小值的下标为 2
// for (var i = 3; i < arr.length; i++) {
// if (arr[minIndex] > arr[i]) {
// minIndex = i
// }
// }
// // for 循环执行完毕 minIndex 就是真实的最小值的下标, 此时交换 真实最小值与假设的最小值的位置即可
// var temp = arr[2]
// arr[2] = arr[minIndex]
// arr[minIndex] = temp
// console.log('第 3 轮选择排序后的数组: ', arr)
// 将上述流程 简化为 for 循环
var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7]
// 0 1 2 3 4 5 6 7 8
console.log('原始数组: ', arr)
/**
* 第几次循环 假设谁是最小值 和谁交换 内层循环从几开始
*
* k === 0 1 0 0 1
* k === 1 2 1 1 2
* k === 2 3 2 2 3
*/
for (var k = 0; k < arr.length; k++) {
var minIndex = k
for (var i = k + 1; i < arr.length; i++) {
if (arr[minIndex] > arr[i]) {
minIndex = i
}
}
var temp = arr[k]
arr[k] = arr[minIndex]
arr[minIndex] = temp
}
console.log('选择排序之后的 数组: ', arr)
3.数据类型之间的区别
* 数据类型之间的区别
* 数据类型分为两种
* 1. 基本数据类型(简单数据类型)
* 2. 引用数据类型(复杂数据类型)
*
* 1. 存储
* 变量的数据存储的地方是 内存中, 内存分为两个 栈内存, 堆内存
* * 基本数据类型存储在 栈内存中, 比如: string number undefined null boolean
* * 复杂数据类型, 将数据本体存放在堆内存中, 比如对象或者数组或者函数
* 然后将指向该内存的地址, 存放在数组名或者对象名或者函数名中
* 数组/对象/函数 名 存放在 栈内存中
*
* 面试官: 数据类型之间有什么区别?
* 基本数据类型有哪些, 然后他们存储的地方是 栈内存中
* 引用数据类型有哪些, 然后他们数据本体存放的地方是 堆内存中, 然后变量名存储的位置是 栈内存中
*
* 基本数据类型内部存储的是值; 引用数据类型内部存储的是地址
*
* 2. 赋值
* 基本数据类型: 赋值以后, 两个变量之间没有任何关系, 相当于将我自己的某一个东西, 复制一份给你, 然后你的就是你的, 我的就是我的
* 例子: 我有一张考试卷, 然后我复制一份给你, 然后你在卷子上书写答案, 并不会影响到我自己原本的这张卷子
*
* 复杂数据类型: 因为变量内部存储的是指向堆内存的地址, 所以在赋值的时候, 其实是将 这个地址给到了另外一个变量
* 那么相当于这两个变量存储的是 同一个 钥匙, 所以操作其中一个变量的时候, 会影响另外一个变量
* 例子: 我房间有一个开门的钥匙, 我将我的钥匙复制一份, 给到你, 那么此时我们两个共同拥有了一个房间的钥匙
* 此时如果我对房间的布局做了修改, 那么你进入房间的时候你能看到布局的修改
* 此时如果你将房间的所有东西全都偷走, 那么我进入房间的时候 能看到房间所有东西都被偷走了
*
* 3. 比较
* 基本数据类型: 就是 值 的比较
* 引用数据类型: 比较的时候 比较的是 存储地址
*
* 4. 传参
* 基本数据类型: 将值拷贝一份传递给形参, 在函数内修改不会影响外界
* 引用数据类型: 将存储地址赋值给形参, 在函数内修改会影响外界
5.