算法 |青训营

60 阅读2分钟

算法与数据

排序之冒泡排序

  1. 比较相邻的两个元素,如果前一个比后一个大,则交换位置
  2. 比较完第一轮的时候,最后一个元素是最大的元素
  3. 这时候最后一个元素是最大的,所以最后一个元素就不需要参与比较大小

image-20211118184349351

第0(i)轮:循环3次=4(长度)-1-0(i)

image-20211118184908141

此时,最后的30和40已经在上一轮比较过了,可以优化

第1(i)轮:循环2次=4(长度)-1-1(i)

image-20211118185051326

此时,最后的20和30也在之前就比较过了,可以优化

第2(i)轮:循环1次=4(长度)-1-2(i)

 <script>
 ​
         /* 冒泡排序 */
         var arr = [40,30,20,10];
         var arrsort = sort(arr);
         console.log(arrsort);
 ​
         function sort(arr) {
             /* 外层循环一次,内层循环一整套
                也就是说,外层只需要循环数组长度-1
                内层循环由于某位的数字已经比较过了,所以可以进行优化:arr.length - 1 - i
              */
             /* 多轮比较 */
             for (var i = 0; i < arr.length - 1; i++) {
                 /* 比较完第一轮 */
                 for (var j = 0; j < arr.length - 1 - i; j++) {
                     /* 每俩个数字开始比较 */
                     // 相邻元素两两对比,元素交换,大的元素交换到后面
                     if (arr[j] > arr[j + 1]) {
                         var temp = arr[j];
                         arr[j] = arr[j + 1];
                         arr[j + 1] = temp;
                     }
                     console.log("循环次数" + j + ":" + arr);
                 }
                 console.log("第" + i + "轮结束");
             }
             return arr;
         }
         
     </script>

image-20230129010823870

算法之递归

递归本质上是将原来的问题,转化为更小的同一问题,大白话就是 一个函数不断的调用自己。

image-20211118192558846

 <script>
 ​
         /* 计算:5!=5*4*3*2*1 */
         /* num:num * num-1 *num-1-1 ... num=1 */
 ​
         function fact(num) {
             /* 把后面那个减一的数又传回自身,也就是5-1=4,把4传回去,那么就可以得到4*3 */
             if (num <= 1) {
                 return 1;
             } else {
                 return (num * fact(num - 1));/* 5*(4*(3*(2*1))) */
             }
         }
         console.log(fact(5));
 ​
     </script>

递归三要素

  1. 一个问题的解可以分解为几个更小的同一题的解——都是相乘
  2. 分解后的子问题只存在数据不一样的问题。——都是相乘
  3. 存在递归终止条件——等于1是终止条件

排序之快速排序

"快速排序"的思想很简单,整个排序过程只需要四步:

  1. 在数据集之中,选择一个元素作为"基准"(pivot)。
  2. 所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
  3. 对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止
  4. 把所有的生成的新的数组元素合并在一起

举例来说,现在有一个数据集 {4,2,5,7,3,9,1}怎么对其排序呢?

第一步,选择中间的元素7作为"基准"。(基准值可以任意选择,但是选择中间的值比较容易理解。)

image-20211118185754465

第二步,按照顺序,将每个元素与"基准"进行比较,形成两个子集,一个"小于7",另一个"大于等于7"

image-20211118190501980

第三步,对两个子集不断重复第一步和第二步,直到所有子集只剩下一个元素为止

image-20211118191003573

第四步,合并所有的元素

image-20211118191102178

 <body>  
     <script>
         var arr = [4,2,5,7,3,9,1];
 ​
         function quickSort(arr){
             if(arr.length<=1){
                 return arr;
             }else{
                 /* 1.选择一个基准,一般是中间,用长度/2,定位下标 */
                 var pivotIndex = Math.floor(arr.length/2);/* 要取整 */
                 /* 2.取出具体的内容 */
                 var pivot = arr.splice(pivotIndex, 1)[0];
                 var left = [];
                 var right = [];
                 for(var i = 0;i<arr.length;i++){
                     if(arr[i] < pivot){
                         left.push(arr[i])
                     }else{
                         right.push(arr[i])
                     }
                 }
                 /*进行左边+基准+右边的合并*/
                 /* console.log(left.concat([pivot],right)); */
                 /* 然后进行一个递归的操作 */
                 return quickSort(left).concat([pivot],quickSort(right));
             }
         }
         var result = quickSort(arr);
         console.log(result);
     </script>
 </body>