持续更新我对算法理解

一、冒泡排序:两两比较,大的放后面,小的放前面;使用两个for循环,一个数就不用比了,所以第一个for循环遍历次数n-1次,第二个for比较次数n 

// 冒泡排序:思路=》两两交换,大的放后面,小的放前面,第一次排序后最大值已在数组末尾
// 代码实现:两个for循环,外层循环控制排序的趟数,内层循环控制比较次数。每趟过后比较次数都应该减一
function sort (arr,n){
    let temp
    for(let i=0;i<n-1;i++){
        for (let j=0;j<n-i-1;j++) {
            if(arr[j]>arr[j+1]){
                temp = arr[j+1]
                arr[j+1] = arr[j]
                arr[j] = temp
            }
        }
    }
    return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [1, 2, 3, 4, 5, 6, 7, 9]
function sort (arr,n){
    let temp
    for(let i=0;i<n-1;i++){
        for (let j=i+1;j<n;j++) {
            if(arr[i]<arr[j]){
                temp = arr[j]
                arr[j] = arr[i]
                arr[i] = temp
            }
        }
    }
    return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [9, 7, 6, 5, 4, 3, 2, 1]

二、选择排序

// 选择排序:找到数组中最大的元素,与数组最后一位元素交换。当只有一个数时,则不需要选择了,所以需要n-1趟排序
// 思路:两个for循环,外层循环控制排序的趟数,内层循环找到当前趟数的最大值,随后与当前趟数数组最后的一位元素交换
function sort (arr,n){
    let temp
    let max=0
    for(let i=0;i<n-1;i++){
        for (let j=0;j<n-i;j++) {
            if(arr[j]>arr[max]){
               max=j 
            }
        }
        temp=arr[max]
        arr[max] = arr[n-1-i]
        arr[n-1-i]=temp
    }
    return arr
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(sort(arr1,n1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9]

三、快速排序 :取一个数作为基准值[以中间项为基准值],小于这个基准数的放在左边,大于基准值的放在右边,递归

三种实现的方式,参考如下

/*
大致分三步:

1、找基准(一般是以中间项为基准)

2、遍历数组,小于基准的放在left,大于基准的放在right

3、递归
*/ 
function quickSort(arr){
    //如果数组<=1,则直接返回
    if(arr.length<=1){
        return arr
    }
    let pointIndex = Math.floor(arr.length/2) //基准值
    let left = []
    let right = []
    let point = arr.splice(pointIndex,1)[0]  //把基准从原来的数组中删除
    for(let i=0;i<arr.length;i++){
        // 小于基准的放在左边
        if(arr[i]<=point){
            left.push(arr[i])
        }else{ //大于基准的放右边
            right.push(arr[i])
        }
    }
    //递归
    return quickSort(left).concat([point],quickSort(right));
}
let arr = [3,2,5,7,9,4,1,6]
console.log(quickSort(arr));
// 快速排序:取一个数作为基准值[以中间项为基准值],小于这个基准数的放在左边,大于基准值的放在右边,递归
function sort (arr,l,r){
    let i = l
    let j =r
    let c = Math.floor((l+r)/2)  //取中间值作为指点,比较
    console.log('c==='+c);
    let temp
    // 左右两端进行扫描,只要两端还没有交替,就一直扫描
    while(i<=j){
        // 寻找直到比支点大的数
        while(arr[i]<arr[c]){
            i++
            console.log('i====='+i);  
        }
        // 寻找直到比支点小的数
        while(arr[c]<arr[j]){
            j--
            console.log('j===='+j);
        }
        // 此时找到了比支点小的数(右边),比支点大的数(左边),将他们交换位置
        if(i<=j){
            temp = arr[i]
            arr[i] = arr[j]
            arr[j] = temp
            i++
            j--
        }
        console.log(arr);
    }
    // “左边”再做排序,直到左边剩下一个数(递归出口)
    if(l<j){
        sort(arr,l,j)
    }
    // "右边"再做排序,直到右边剩下一个数(递归出口)
    if(i<r){
        sort(arr,i,r)
    }
    console.log(arr);
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
sort(arr1,0,n1-1)
function quickSort(arr, left, right) {
    /*
     * len为数组的长度;
     * left为需要数组中参与排序的起始点;right为数组中参与排序的终止点;
     * left如果有传数字那么就为left,没有传参则为0;
     * right如果有传参那么就为right,没有传参则为len-1;
     * 有传参可能会部分排序可能不会排序,没传参默认排序整个数组;
     * partitionIndex为分组界限;
     */
    var len = arr.length,
        partitionIndex,
        left = typeof left !== 'number' ? 0 : left,
        right = typeof right !== 'number' ? len - 1 : right;

    // 如果需要排序的起始索引小于终止索引则执行排序;递归的终止条件;
    if (left < right) {

        // partition的返回值作为partitionIndex来分隔数组;
        // 索引partitionIndex左边的元素均小于arr[partitionIndex];
        // 右边的元素均大于arr[partitionIndex];
        partitionIndex = partition(arr, left, right);

// 数组中小于arr[partitionIndex]的部分(索引left到partitionIndex-1)再次使用quickSort排序;
        quickSort(arr, left, partitionIndex - 1);

// 数组中大于arr[partitionIndex]的部分(索引partitionIndex+1到right)再次使用quickSort排序;
        quickSort(arr, partitionIndex + 1, right);
    }
    // 递归执行直到不满足left<right;返回本身;
    return arr;
}

function partition(arr, left, right) {
    /*
     * 这部分是具体实现排序的部分;
     * 将left赋值给pivot,作为参照物,因为left在最左边,只需要从左到右比较一遍即可判断整个数组;
     * index索引是arr中待交换位置;
     */
    var pivot = left,
        index = pivot + 1;
    // for循环从参照物arr[pivot]下一个元素arr[pivot+1]开始一直比较到子数组结束arr[right];
    for (var i = index; i <= right; i++) {

  // 循环中如果有任何小于参照物的,就将他交换到index的位置,然后index向右移动到下一个位置;
        if (arr[i] < arr[pivot]) {
            swap(arr, i, index);
            index++;
        }
    }
    /*
     * 因为每次都是交换完后index移动到下一个位置,所以在循环结束时,index仍为待交换的位置;
     * 此时索引pivot+1到index-1的元素都小于参照物arr[pivot];
     */

    // 交换pivot和index-1索引的值之后index-1索引左边全都是小于arr[index-1]的元素;
    swap(arr, pivot, index - 1);

    // 返回index-1作为拆分子数组的分界线;
    return index - 1;
}
/*
 * 普通的交换,将a[i]和a[j]的数值交换;
 */
function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(quickSort(arr1,0,n1-1));

插入排序

归并排序

堆排序

希尔排序

基数排序

递归

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值