_3 案例

day3 _ 案例

案例1
   // // 面试题
    // function fn(obj) {
    //   // 此时 形参obj 存储的内容就是 空间地址(xf001)
    //   // 利用 形参obj 修改 name 属性的值
    //   // 把 全局obj 这个空间内的 name 修改为 Rose 了
    //   obj.name = 'Rose'

    //   // 此时给 形参obj 从新赋值为一个新的对象空间地址(xf002)
    //   obj = new Object()
    //   // 此时 形参obj 修改name 属性修改的是 xf002 地址内的 name
    //   // 不影响 全局obj
    //   obj.name = 'Tom'
    // }
    // // 全局obj 被赋值为一个对象空间地址(xf001), 内部存储一个 name:'Jack'
    // var obj = { name: 'Jack' }
    // // 调用 fn , 把 全局obj 传递进去, 真实给进去的是 空间地址(xf001)
    // fn(obj)
    // console.log(obj.name) // Rose


    // // 面试题
    // function fn(obj) {
    //   // 本身私有空间内存在一个私有变量 obj, 接受的值是 全局obj(xf001)
    //   // 预解析阶段, 声明一个 obj 变量, 没有意义
    //   obj.name = 'Rose'
    //   var obj = new Object()
    //   obj.name = 'Tom'
    // }
    // var obj = { name: 'Jack' }
    // fn(obj)
    // console.log(obj.name) // Rose


    // // 面试题
    // function fn() {
    //   // 在函数内代码执行之前, 会进行预解析
    //   // 在 fn 空间内声明一个私有变量, 叫做 obj, 但是没有赋值, 此时 obj 是 undefined

    //   // 执行代码
    //   // obj.name = 'Rose'
    //   // 此时 obj 是 undefined, 你执行的就是 undefined.name = 'Rose'
    //   obj.name = 'Rose'
    //   var obj = new Object()
    //   obj.name = 'Tom'
    // }
    // var obj = { name: 'Jack' }
    // fn(obj)
    // console.log(obj.name)


    // 面试题
    function fn() {
      // 此时 obj 就是 全局obj(xf001)
      // 给 全局obj 内修改 name 属性
      obj.name = 'Rose'
      // 给 全局obj 从新赋值为一个新的对象(xf002)
      obj = new Object()
      // 给 全局obj(xf002) 赋值一个 name 属性为 Tom
      obj.name = 'Tom'
    }
    var obj = { name: 'Jack' }
    fn(obj)

    // 打印的是全局obj
    // 因为 fn 函数的执行, 把全局obj 修改为了 (xf002)
    console.log(obj.name)
案例2 数组操作案例
 /*
  数组操作 案例
*/
var arr = [ 10, 20, 12, 31, 4, 5, -7, 33, 11 ]

// 案例1: 找到数组内的最大值
/*
  逻辑:
    + 假设一个数据是最大值
    + 依次进行比较, 只要比假设的大, 就进行替换
    + 数组遍历完毕以后, 最大值出现了
*/
// 1. 假设数组的 [0] 位置数据最大
// var max = arr[0]

// // 2. 循环遍历数组
// for (var i = 1; i < arr.length; i++) {
//   // 3. 判断数组内的每一个数据是否比假设的大
//   if (arr[i] > max) {
//     // 替换
//     max = arr[i]
//   }
// }
// console.log(max)


// 案例2: 找到数组内最大值的索引
/*
  逻辑:
    + 假设一个索引位置是最大值的索引位置
    + 一次进行比较, 只要比假设的大, 进行索引的替换
*/
// 1. 假设数组的 0 索引位置最大
// var maxIndex = 0
// // 2. 遍历数组
// for (var i = 1; i < arr.length; i++) {
//   // 3. 比较
//   if (arr[i] > arr[maxIndex]) {
//     // 替换
//     maxIndex = i
//   }
// }
// console.log(maxIndex)
// console.log(arr[maxIndex])
案例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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值