JavaScript 数据结构与算法 之 排序算法

简介: JavaScript 数据结构与算法 之 排序算法

排序算法

冒泡排序

function bubbleSort(array, compareFn = defaultCompare) {
  const { length } = array;
  for (let i = 0; i < length; i++) {
    for( let j = 0; j < length - 1; j++) {
      if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
        swap(array, j, j + 1);
      }
    }
  }
  return array;
}
function swap(array, a, b) {
  [array[a], array[b]] = [array[b], array[a]];
}

优化,从内循环中减去外循环中已跑过的轮数

function modifiedBubbleSort(array, compareFn = defaultCompare) {
  const { length } = array;
  for (let i = 0; i < array.length; i++) {
    for (let j = 0; j < array.length - 1 - i; j++) {
      if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
        swap(array, j, j + 1);
      }
    }
  }
  return array;
}

优化,设置标志性变量 pos,隐喻记录每趟排序中最后一次进行交换的位置,由于 pos 位置之后的记录均已狡猾到位,所以下一趟排序时,只要扫描到 pos 位置即可

function bubbleSort2(array, compareFn = defaultCompare) {
  let i = array.length - 1; // 初始时,最后位置保持不变
  while (i > 0) {
    let pos = 0; // 每趟开始时,无交换记录
    for (let j = 0; j < i; j++) {
      if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
        pos = j; // 记录交换的位置
        swap(array, j, j + 1);
      }
    }
    i = pos; // 为下一趟排序做准备
  }
  return array;
}

优化,传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值,从而使排序趟数几乎少了一半。

function bubbleSort3(array, compareFn = defaultCompare) {
  let low = 0;
  let high = array.length - 1;
  let tmp, j;
  while (low < high) {
    for (j = low; j < high; ++j) { // 正向冒泡找到最大者
      if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
        swap(array, j, j + 1);
      }
    }
    --high; // 修改 high 值,前移一位
    for (j = high; j > low; --j) { // 反向冒泡,找到最小者
      if (compareFn(array[j], array[j - 1]) === Compare.LESS_THAN) {
        swap(array, j, j - 1);
      }
    }
    --low;
  }
  return array;
}

选择排序

找到数据结构的最小值并将其放置在第一位,接着找到第二小的并将其放置在第二位,以此类推

function selectionSort(array, compareFn = defaultCompare) {
  const { length } = array;
  let indexMin;
  for (let i = 0; i < length - 1; i++) {
    indexMin = i;
    for (let j = i; j < length; j++) {
      if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) {
        indexMin = j;
      }
    }
    if (i !== indexMin) {
      swap(array, i, indexMin);
    }
  }
  return array;
};

插入排序

插入排序每次排一个数组项,以此方式构建最后的排序数组。假定第一项已经排序,接着,它和第二项进行比较——第二项是应该待在原位还是插到第一项之前呢?这样,头两项就已正确排序,接着和第三项比较,以此类推

function insertionSort(array, compareFn = defaultCompare) {
  const { length } = array;
  let tmp;
  for (let i = 1; i < length; i++) {
    let j = i;
    tmp = array[i];
    while (j > 0 && compareFn(array[i - 1], tmp) === Compare.BIGGER_THAN) {
      array[j] = array[j - 1];
      j--;
    }
    array[j] = tmp;
  }
  return array;
};
  • 希尔排序
简单插入排序的改进版,优先比较较远距离的元素,也叫缩小增量排序
实现:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序
  1. 选择一个增量序列t1, t2,...,tk,其中 ti > tj,tk = 1
  2. 按增量序列个数 k,对序列进行 k 趟排序
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度
function shellSort(arr) {
  var len = arr.length,
      temp,
      gap = 1;
  // 动态定义间隔序列
  while(gap < len /5) {
    gap = gap * 5 + 1;
  }
  for (gap; gap > 0; gap = Math.floor(gap/5)) {
    for (var i = gap; i < len; i++) {
      temp = arr[i];
      for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j];
      }
      arr[j + gap] = temp;
    }
  }
  return arr;
}

归并排序

归并排序是一种分而治之算法。思想是将原始数据切分成较小的数组,直到每个小数组只有一个位置,接着将 小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。

function mergeSort(array, compareFn = defaultCompare) {
  if (array.length > 1) {
    const { length } = array
    const middle = Math.floor(length / 2);
    const left = mergeSort(array.slice(0, middle), compareFn);
    const right = mergeSort(array.slice(middle, length), compareFn);
    array = merge(left, right, compareFn);
  }
  return array;
}
function merge(left, right, compareFn) {
  let i = 0;
  let j = 0;
  const result = [];
  while (i < left.length && j < right.length) {
    if (compareFn(left[i], right[j]) === Compare.LESS_THAN) {
      result.push(left[i++]);
    } else {
      result.push(right[j++]);
    }
  }
  if (i < left.length) {
    result.concat(left.slice(i));
  } else {
    result.concat(right.slice(j));
  }
  return result;
}

快速排序

步骤

  1. 首先,从数组中选择一个值作为主元,即数组中间那个值
  2. 划分:创建两个指针(引用),左边一个指向数组的第一个值,右边指向数组最后一个值。移动左指针,直到我们找到一个比主元大的值,接着移动右指针直到找到一个比主元小的值,然后交换他们,重复这个过程,直到左指针超过了右指针。这个过程将使得比主元小的值都排在主元之前,比主元大的值都排在主元之后
  3. 算法对划分后的小数组(较主元小的值组成的子数组,以及较主元大的值组成的子数组)重复之前的两个步骤,直至数组已经完全排序。
function quicksort(array, compareFn = defaultCompare) {
  return quick(array, 0, array.length - 1, compareFn);
}
相关文章
|
20天前
|
运维 监控 JavaScript
内网网管软件中基于 Node.js 的深度优先搜索算法剖析
内网网管软件在企业网络中不可或缺,涵盖设备管理、流量监控和安全防护。本文基于Node.js实现深度优先搜索(DFS)算法,解析其在网络拓扑遍历中的应用。通过DFS,可高效获取内网设备连接关系,助力故障排查与网络规划。代码示例展示了图结构的构建及DFS的具体实现,为内网管理提供技术支持。
38 11
|
4月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
124 1
|
13天前
|
存储 搜索推荐 算法
算法系列之排序算法-堆排序
堆排序(Heap Sort)是一种基于堆数据结构的比较排序算法。它的时间复杂度为 $O(nlogn)$,并且是一种原地排序算法(即不需要额外的存储空间)。堆排序的核心思想是利用堆的性质来维护一个最大堆或最小堆,然后逐步将堆顶元素(最大值或最小值)取出,放到数组的末尾,最终得到一个有序的数组。
28 8
算法系列之排序算法-堆排序
|
7天前
|
算法 JavaScript 前端开发
Javascript常见算法详解
本文介绍了几种常见的JavaScript算法,包括排序、搜索、递归和图算法。每种算法都提供了详细的代码示例和解释。通过理解这些算法,你可以在实际项目中有效地解决各种数据处理和分析问题。
50 21
|
17天前
|
监控 网络协议 算法
基于问题“如何监控局域网内的电脑”——Node.js 的 ARP 扫描算法实现局域网内计算机监控的技术探究
在网络管理与安全领域,监控局域网内计算机至关重要。本文探讨基于Node.js的ARP扫描算法,通过获取IP和MAC地址实现有效监控。使用`arp`库安装(`npm install arp`)并编写代码,可定期扫描并对比设备列表,判断设备上线和下线状态。此技术适用于企业网络管理和家庭网络安全防护,未来有望进一步提升效率与准确性。
33 8
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
94 29
|
1月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
107 25
|
1月前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
77 23
|
2月前
|
JavaScript 算法 安全
深度剖析:共享文件怎么设置密码和权限的 Node.js 进阶算法
在数字化时代,共享文件的安全性至关重要。本文聚焦Node.js环境,介绍如何通过JavaScript对象字面量构建数据结构管理文件安全信息,包括使用`bcryptjs`库加密密码和权限校验算法,确保高效且安全的文件共享。通过实例代码展示加密与权限验证过程,帮助各行业实现严格的信息资产管理与协作。
|
2月前
|
存储 监控 算法
局域网网络管控里 Node.js 红黑树算法的绝妙运用
在数字化办公中,局域网网络管控至关重要。红黑树作为一种自平衡二叉搜索树,凭借其高效的数据管理和平衡机制,在局域网设备状态管理中大放异彩。通过Node.js实现红黑树算法,可快速插入、查找和更新设备信息(如IP地址、带宽等),确保网络管理员实时监控和优化网络资源,提升局域网的稳定性和安全性。未来,随着技术融合,红黑树将在网络管控中持续进化,助力构建高效、安全的局域网络生态。
64 9

热门文章

最新文章