day3 _ 案例
案例1
function fn() {
obj.name = 'Rose'
obj = new Object()
obj.name = 'Tom'
}
var obj = { name: 'Jack' }
fn(obj)
console.log(obj.name)
案例2 数组操作案例
var arr = [ 10, 20, 12, 31, 4, 5, -7, 33, 11 ]
案例3 选择排序
选择排序
+ 目的: 为了锻炼逻辑思维, 锻炼数组的基本操作
+ 逻辑:
=> 第一轮:
-> 找到数组内最小的数据的索引
-> 把最小的移动到最前面
=> 第二轮:
-> 找到除了第一个以外的内容中最小的数据的索引
-> 把第二次找到的数字放在第二个位置
=> 重复 length - 1 轮
// 准备原始数组
var arr = [ 4, 8, 5, 2, 9, 7, 3, 1, 6 ]
console.log('原始数组 : ', arr)
// 1. 如何交换数组内两个数据的位置
// 利用一个变量当做中间值转换
// var tmp = arr[0]
// arr[0] = arr[1]
// arr[1] = tmp
// console.log('交换之后 : ', arr)
// 2. 第一轮比较
// // 2-1. 假设索引 0 位置最小
// var minIndex = 0
// // 2-2. 遍历数组
// for (var i = 1; i < arr.length; i++) {
// // 2-3. 比较
// if (arr[i] < arr[minIndex]) minIndex = i
// }
// // 2-4. 交换位置
// // [0] 和 [minIndex] 位置交换
// if (minIndex !== 0) {
// console.log('执行交换代码')
// var tmp = arr[0]
// arr[0] = arr[minIndex]
// arr[minIndex] = tmp
// }
// console.log('一轮之后 : ', arr)
// 3. 重复步骤2: 重复 length-1 轮
/*
总结规律
j minIndex 里层循环的开始 交换的索引位置
0 0 1 0
1 1 2 1
2 2 3 2
*/
for (var j = 0; j < arr.length - 1; j++) {
// 完整执行步骤2
// 2-1. 假设索引 j 位置最小
var minIndex = j
// 2-2. 遍历数组
for (var i = j + 1; i < arr.length; i++) {
// 2-3. 比较
if (arr[i] < arr[minIndex]) minIndex = i
}
// 2-4. 交换位置
// [j] 和 [minIndex] 位置交换
if (minIndex !== j) {
var tmp = arr[j]
arr[j] = arr[minIndex]
arr[minIndex] = tmp
}
}
console.log('排序之后 : ', arr)
案例4 冒泡排序
/*
排序算法 - 冒泡排序
+ 逻辑:
=> 第一轮:
-> 两两比较, 如果前一个大于后一个, 交换位置
-> 一轮过后, 最大的放在了最后面
=> 重复第一轮:
-> 重复 length - 1 轮
*/
// 准备原始数组
var arr = [ 4, 8, 5, 1, 9, 7, 2, 3, 6 ]
console.log('原始数组 : ', arr)
// 第一轮
// 直接遍历数组
// 最后一位的索引是 length-1
// 当 arr[i] 到达最后一个的时候, 比较的是 arr[length-1] > arr[length]
// for (var i = 0; i < arr.length - 1; i++) {
// // 依次比较当前这个和下一个
// // 当前这个 ? arr[i]
// // 下一个 ? arr[i + 1]
// if (arr[i] > arr[i + 1]) {
// var tmp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = tmp
// }
// }
// console.log('一轮之后 : ', arr)
// 重复第一轮
// 比较 length - 1 轮就可以了
// j === 0 的时候, 第 1 轮, 少 0 次
// j === 1 的时候, 第 2 轮, 少 1 次
// j === 2 的时候, 第 3 轮, 少 2 次
// for (var j = 0; j < arr.length - 1; j++) {
// // 完整执行步骤1
// for (var i = 0; i < arr.length - 1 - j; i++) {
// console.log(arr[i], ' > ', arr[i + 1])
// if (arr[i] > arr[i + 1]) {
// var tmp = arr[i]
// arr[i] = arr[i + 1]
// arr[i + 1] = tmp
// }
// }
// console.log('一轮之后 : ', arr)
// }
for (var j = 0; j < arr.length - 1; j++) {
// 准备一个变量表示是否交换了
var flag = false // 默认没有交换
for (var i = 0; i < arr.length - 1 - j; i++) {
if (arr[i] > arr[i + 1]) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
// 这里的代码只要执行, 就表示交换了
// 只要交换了, 推翻我的假设
flag = true
}
}
// 只要 flag 是 false, 那么可以直接结束循环了
if (!flag) break
}
console.log('排序之后 : ', arr)
案例5 计数排序
/*
计数排序
+ 逻辑
=> 准备一个原始数组(001)
=> 准备一个新的空数组(002)
=> 遍历原始数组(001) 把每一个数据当做新数组(002)的索引
=> 在新数组(002) 内的值当做个数来填充
=> 遍历新数组(002) 把索引当数据填充回去, 填充多少个(值是多少填充多少个)
*/
var arr = [ 10, 20, 10, 11, 3, 5, 7, 4, 3, 2, 1, 3, 4, 5, 6, 11 ]
console.log('原始数组 : ', arr)
// 准备一个新的空数组
var tmp = []
// 功能1: 计数(什么数字有多少个)
for (var i = 0; i < arr.length; i++) {
// 随着循环 arr[i] 分别是原始数组内的每一个数据
// console.log(arr[i])
// 把原始数组内的数据当做新数组内的索引使用
var index = arr[i]
// 判断 tmp 数组内 [index] 位置是否有数据
tmp[index] ? tmp[index]++ : tmp[index] = 1
}
console.log('计数数组 : ', tmp)
// 原始数组可以置空
arr.length = 0
console.log(arr)
// 功能2: 回填
for (var i = 0; i < tmp.length; i++) {
// 判断如果该索引位置没有值, 不需要回填
if (!tmp[i]) continue
// 向原始数组内追加内容
var count = tmp[i] // 多少个
var data = i // 回填的数据
for (var j = 0; j < count; j++) {
arr[arr.length] = data
}
}
console.log('排序之后 : ', arr)
// 第一次分析
// 判断 tmp 内 [10] 是否有数据
// 没有, 我就赋值为 1
// tmp[10] = 1
// 判断 tmp 内 [20] 是否有数据
// 没有, 我就赋值为 1
// tmp[20] = 1
// 判断 tmp 内 [10] 是否有数据
// 有, 数据++
// tmp[10]++
案例6 递归函数
/*
递归函数
+ 函数的递归调用
+ 是一种函数的调用方式
=> 一个函数自己调用自己本身, 并且设置了正确的折返条件
*/
// function fn(n) {
// // 我需要求 几的阶乘, 就把n赋值为几
// // 到达折返点的时候
// if (n === 1) return 1
// // 没有到达折返点的时候
// return n * fn(n - 1)
// }
// // 将来我需要求 5 的阶乘的时候
// var res = fn(5)
// console.log(res)
// 案例: 递归求最大公约数
// function fn(max, min) {
// // 先写折返点
// if (max % min === 0) return min
// // 未到达折返点
// return fn(min, max % min)
// }
// // 我需要求最大公约数的时候
// var res = fn(20, 19)
// console.log(res)
// 案例: 斐波那契数列
// 数列: 1 1 2 3 5 8 13 21 34 55 ...
// 规则: 第一位和第二位必然是 1
// 第三位开始每一位是前面两位的和
// 书写一个函数求第 n 位数字是什么
function fn(n) {
// n 表示的是第 n 位
// 折返点
if (n === 1 || n === 2) return 1
// 未到达折返点
return fn(n - 2) + fn(n - 1)
}
// 将来你想求第 10 位数字是什么的时候
var res = fn(10)
console.log(res)
案例7 快速排序
/*
排序算法 - 快速排序(递归二分法)
+ 逻辑:
=> 把一个数组拿出最中间一个数据
=> 把数组中剩下的数据和这个中心位置数据比较
=> 准备两个新数组, 一个叫做 left 一个叫做 right
=> 小的放在 left 内, 大的放在 right 内
=> 递归把 左边的数组 和 右边的数组 按照之前的方法继续
*/
// 准备原始数组
var arr = [ 4, 7, 5, 2, 6, 3, 9, 1, 8 ]
// 写个函数
// function quickSort(ary) {
// // 折返点
// if (ary.length <= 1) return ary
// // 未到达折返点
// // 1. 中心索引
// var centerIndex = parseInt(ary.length / 2)
// // 2. 从原始数组中截取出中心数据 splice
// var center = ary.splice(centerIndex, 1)[0]
// // 3. 准备两个空数组
// var left = [], right = []
// // 4. 遍历数组
// for (var i = 0; i < ary.length; i++) {
// // 判断放在左边还是右边
// if (ary[i] < center) left.push(ary[i])
// else right.push(ary[i])
// }
// // 技巧: 拼接数组
// // left 按照 quick 规则执行一遍
// // right 按照 quick 规则执行一遍
// // left center right 拼接在一起
// return [ ...quickSort(left), center, ...quickSort(right) ]
// }
function quickSort(ary) {
// 到达折返点
if (ary.length <= 1) return ary
// 未到达折返点
// 找到中心数据
var center = ary.splice(parseInt(ary.length / 2), 1)[0]
// 准备左右数组
var left = [], right = []
// 遍历 ary 决定放在左边还是右边
for (var i = 0; i < ary.length; i++) {
ary[i] < center ? left.push(ary[i]) : right.push(ary[i])
}
// 拼接在一起(递归)
return [ ...quickSort(left), center, ...quickSort(right) ]
}
// 将来使用的时候
var res = quickSort(arr)
console.log(res)
// 展开运算符 ...
// 当展开运算符展开数组的时候, 就等价于数组去掉括号
// var a1 = [ 10, 20, 30 ]
// var a2 = [ 100, 200, 300 ]
// var a3 = [ ...a1, ...a2 ]
// console.log(a3)
案例8 插入排序
/*
排序算法 - 插入排序
+ 逻辑
=> 直接遍历数组(从 [1] 开始遍历)
-> 把当前这个索引位置数据拿出来
-> 从当前位置的前一个位置开始向前比较
-> 如果 没循环到头 && 我比前一个大
+ 让前一个占领当前的位置
-> 把自己放在这个位置
*/
// 准备原始数组
var arr = [ 4, 5, 2, 7, 6, 3, 9, 1, 8 ]
console.log('原始数组 : ', arr)
// 目标: 按照 插入排序的 逻辑, 把 7 这个数据插入到 [0] 位置
// 1. 把 7 这个数据复制出来
// var tmp = arr[3]
// console.log('抽出来的一张 牌 : ', tmp)
// // 2. 开始向前比较
// // 2-1. 定义初始变量
// var j = 3 - 1
// // 2-2. 开始循环
// while (j >= 0 && tmp > arr[j]) {
// // 做的事情
// arr[j + 1] = arr[j]
// // 2-3. 修改初始变量
// j--
// }
// // 3. 把抽出来的牌插入回去
// arr[j + 1] = tmp
// console.log(arr)
// 目的: 把原始数组遍历, 从 [1] 开始, 每一个数字经历步骤1 过程
// for (var i = 1; i < arr.length; i++) {
// // 完整执行步骤1
// // 1. 把 7 这个数据复制出来
// var tmp = arr[i]
// // 2. 开始向前比较
// // 2-1. 定义初始变量
// var j = i - 1
// // 2-2. 开始循环
// while (j >= 0 && tmp > arr[j]) {
// // 做的事情
// arr[j + 1] = arr[j]
// // 2-3. 修改初始变量
// j--
// }
// // 3. 把抽出来的牌插入回去
// arr[j + 1] = tmp
// }
// 插入排序
for (var i = 1; i < arr.length; i++) {
// 1.
var tmp = arr[i]
// 2.
var j = i - 1
while (j >= 0 && tmp > arr[j]) {
arr[j + 1] = arr[j]
j--
}
// 3.
arr[j + 1] = tmp
}
console.log('排序之后 : ', arr)