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);
}
相关文章
|
28天前
|
JavaScript 算法 安全
深度剖析:共享文件怎么设置密码和权限的 Node.js 进阶算法
在数字化时代,共享文件的安全性至关重要。本文聚焦Node.js环境,介绍如何通过JavaScript对象字面量构建数据结构管理文件安全信息,包括使用`bcryptjs`库加密密码和权限校验算法,确保高效且安全的文件共享。通过实例代码展示加密与权限验证过程,帮助各行业实现严格的信息资产管理与协作。
|
1月前
|
存储 监控 算法
局域网网络管控里 Node.js 红黑树算法的绝妙运用
在数字化办公中,局域网网络管控至关重要。红黑树作为一种自平衡二叉搜索树,凭借其高效的数据管理和平衡机制,在局域网设备状态管理中大放异彩。通过Node.js实现红黑树算法,可快速插入、查找和更新设备信息(如IP地址、带宽等),确保网络管理员实时监控和优化网络资源,提升局域网的稳定性和安全性。未来,随着技术融合,红黑树将在网络管控中持续进化,助力构建高效、安全的局域网络生态。
50 9
|
1月前
|
存储 监控 JavaScript
深度探秘:运用 Node.js 哈希表算法剖析员工工作时间玩游戏现象
在现代企业运营中,确保员工工作时间高效专注至关重要。为应对员工工作时间玩游戏的问题,本文聚焦Node.js环境下的哈希表算法,展示其如何通过快速查找和高效记录员工游戏行为,帮助企业精准监测与分析,遏制此类现象。哈希表以IP地址等为键,存储游戏网址、时长等信息,结合冲突处理与动态更新机制,确保数据完整性和时效性,助力企业管理层优化工作效率。
34 3
|
2月前
|
监控 算法 JavaScript
基于 Node.js Socket 算法搭建局域网屏幕监控系统
在数字化办公环境中,局域网屏幕监控系统至关重要。基于Node.js的Socket算法实现高效、稳定的实时屏幕数据传输,助力企业保障信息安全、监督工作状态和远程技术支持。通过Socket建立监控端与被监控端的数据桥梁,确保实时画面呈现。实际部署需合理分配带宽并加密传输,确保信息安全。企业在使用时应权衡利弊,遵循法规,保障员工权益。
52 7
|
3月前
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
3月前
|
数据采集 存储 JavaScript
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
本文介绍了如何使用Puppeteer和Node.js爬取大学招生数据,并通过代理IP提升爬取的稳定性和效率。Puppeteer作为一个强大的Node.js库,能够模拟真实浏览器访问,支持JavaScript渲染,适合复杂的爬取任务。文章详细讲解了安装Puppeteer、配置代理IP、实现爬虫代码的步骤,并提供了代码示例。此外,还给出了注意事项和优化建议,帮助读者高效地抓取和分析招生数据。
154 0
如何使用Puppeteer和Node.js爬取大学招生数据:入门指南
|
4月前
|
JavaScript 数据安全/隐私保护
2024了,你会使用原生js批量获取表单数据吗
2024了,你会使用原生js批量获取表单数据吗
76 4
|
4月前
|
前端开发 JavaScript
JS-数据筛选
JS-数据筛选
53 7
|
4月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
|
4月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
58 0
数据结构与算法学习十四:常用排序算法总结和对比

热门文章

最新文章