常见的排序和查找算法(js实现)

本文详细介绍了几种常见的查找方法,包括顺序查找、二分法查找、二叉查找树和斐波那契查找,以及它们的时间复杂度。同时,还探讨了四种排序算法:冒泡排序、直接插入排序、选择排序和归并排序,分析了它们的平均时间复杂度和工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.常见的查找方法:

1.顺序查找:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给 定值比较,若某个记录的关键字和给定值相同,则查找成功;如果直到最后一个(或第一个)记录,关键字和给定值比较都不相等,则查找不成功。

 var arr = [1,4,53,6,9,3]
  function find(arr,num){
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] == num) {
        return i
      }
    }
    return null
  }
  console.log(find(arr,3));              顺序查找的时间复杂度为O(n)

2.二分法查找:前提是必须有序的,用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表

 const arr1 = [1, 4, 5, 8, 12, 16, 18]
        function foo1(arr, num) {
            let leftIndex = 0 
            let rightIndex = arr.length - 1
            while (leftIndex <= rightIndex) {
                let mid = Math.floor((leftIndex + rightIndex) / 2)
                if (num === arr[mid]) { // 找到返回mid
                    return mid
                } else if (num > arr[mid]) { // 比中间值大,说明在 mid 到 rightIndex 之间;否则就在 mid 到 leftIndex 之间
                    leftIndex = mid + 1
                } else {
                    rightIndex = mid - 1
                }
            }
            return -1 // 没找到返回-1
        }
        console.log(foo1(arr1, 18))           二分法查找时间复杂度O(logn)

3、二叉查找树:

若它的左子树不为空,则左子树上所有节点的值均小于根节点的值;

若它的右子树不为空,则右子树上所有节点的值均大于根节点的值;

它的左右子树也是二叉排序树。

//二叉排序树的查找
    function treeSearch(target, root) {
        if (root) {
            if (target == root.value) {
                return true;
            } else if (target < root.value) {
                return treeSearch(target, root.left);
            } else {
                return treeSearch(target, root.right);
            }
        } else {
            return false;
        }
    }

4、斐波那契查找:前提是有序序列查找,斐波那契查找采用和二分查找相似的区间分割策略,都是通过不断的分割区间缩小搜索的范围。

过程:构建斐波那契数列;f(n) = f(n-1) + f(n-2)

计算数组长度对应的斐波那契数列元素个数;

对数组进行填充;

循环进行区间分割,查找中间值;

判断中间值和目标值的关系,确定更新策略;

function fibSearch(target, arr) {
        //简易斐波那契数列
        function fib(n) {
            if (n <= 1) {
                return 1;
            } else {
                return fib(n - 1) + fib(n - 2);
            }
        }
        var low = 0;
        //记录数组长度,后续会填充数组
        const temp = arr.length - 1;
        var k = 0;
        var mid = 0;
        while (fib(k) - 1 < arr.length) {
            k++;
        }
        high = fib(k) - 1;
        //将arr数组填充至fib(k)的长度
        for (var i = temp; i < high; i++) {
            arr.push(arr[temp]);
        }
        while (low <= high) {
            mid = low + fib(k - 1) - 1;
            if (arr[mid] < target) {
                low = mid + 1;
                k = k - 2;
            } else if (arr[mid] > target) {
                high = mid - 1;
                k = k - 1;
            } else {
                return mid <= temp ? mid : temp;
            }

        }
        return -1;
    }                                     斐波那契查找时间复杂度O(logn)

二、常见的排序方法:

1.冒泡排序:对相邻的元素进⾏两两⽐较,顺序相反则进⾏交换,这样每⼀次会将最⼩或最⼤的元素“浮”到顶端,最终达到完全有序。

var arr = [2,5,6,7,8,9,3,1,4]
   function paixu(arr){
    if (!Array.isArray(arr) || arr.length <= 1) return arr;
    for (let i = 0; i < arr.length; i++) {
      for (let j = 0; j < arr.length-1-i; j++) {
       if (arr[j] > arr[j+1]) {
          let a = arr[j]
          arr[j] = arr[j+1]
          arr[j+1] = a
       }
      }
    }
    return arr
   }
console.log(paixu(arr));                      平均时间复杂度O(n*n)

2.直接插⼊排序: 每⼀步将⼀个待排序的记录,插⼊到前⾯已经排好序的有序序列中去,直到插完所有元素为⽌。

function insertSort(arr) {
      if (!Array.isArray(arr) || arr.length <= 1) return; 
      for (let i = 1; i < arr.length; i++) { // 循环从 1 开始,0 位置为默认的已排序的序列
        let temp = arr[i];                   // 保存当前需要排序的元素
        let j = i - 1;
        //在当前已排序序列中⽐较,如果⽐需要排序的元素⼤,就依次往后移动位置
        while (j >= 0 && arr[j] > temp) { 
          arr[j + 1] = arr[j];
          j--;
        }
        arr[j + 1] = temp;                   // 将找到的位置插⼊元素
      }
      return arr;
    }
    console.log(insertSort([1, 6, 3, 2, 5]));        平均时间复杂度O(n*n)

3.选择排序:为每⼀趟从待排序的数据元素中选择最⼩(或最⼤)的⼀个元素作为⾸元素,直到所有元素排完为⽌。

var arr = [2,1,3,4,9,6]
    function selectSort(arr){
      let min;                    //定义min,缓存当前区间最小值的索引
      for (let i = 0; i < arr.length; i++) {
        min = i                    //初始化min为当前区间第一个元素
        for (let j = i; j < arr.length; j++) { //i、j分别定义当前区间的上下界
          if (arr[min] > arr[j]) {
            min =j
          }
        }
        if (min != i) {//如果minIndex对应元素不是目前的头部元素,则交换两者 
          [arr[i],arr[min]]= [arr[min],arr[i]]
        }
      }
      return arr
    }
   console.log(selectSort(arr));                平均时间复杂度O(n*n)

4.归并排序:递归的将数组两两分开直到只包含⼀个元素,然后 将数组排序合并,最终合并为排序好的数组。

function mergeSort(arr) {
  if (arr.length < 2) {
    return arr;
  }
  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  return merge(left, right);
}

function merge(left, right) {
  let res = [];
  let i = 0;
  let j = 0;
  while (i < left.length && j < right.length) {
    if (left[i] < right[j]) {
      res.push(left[i]);
      i++;
    } else {
      res.push(right[j]);
      j++;
    }
  }
  if (i < left.length) {
    res.push(...left.slice(i));
  } else {
    res.push(...right.slice(j));
  }
  return res;
}
// console.log(mergeSort([3, 6, 2, 4, 1]));          时间复杂度 nlog(n)

5.快速排序: 通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的所有数据都⽐另外⼀部分的所有数据都要⼩

//快速排序
    var arr= [0,2,1,8,4,5,9]
    function quickSort(arr) {
      if (arr.length <= 1) {
        return arr;
      }
      var midIndex = Math.floor(arr.length / 2);
      var mid = arr.splice(midIndex, 1)[0];
      var left = [];
      var right = [];

       for (var i = 0; i < arr.length; i++) {
        if (arr[i] < mid) {
          left.push(arr[i]);
        } else {
          right.push(arr[i]);
        }
      }
      return quickSort(left).concat([mid], quickSort(right));
    };
  console.log(quickSort(arr));

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值