资讯专栏INFORMATION COLUMN

Javascript常见排序算法的笔记

617035918 / 807人阅读

摘要:排序算法主要针对的是数组,所以,在开始学习之前,我们先自己新建一种数据结构来方便我们的学习。统计执行次数冒泡排序比较相邻两个数的大小,如果前面的数大于后面,则交换这两个数的位置。所以我们把数列分割成不超过两个元素的数组,然后将其合并。

  排序算法主要针对的是数组,所以,在开始学习之前,我们先自己新建一种数据结构来方便我们的学习。

</>复制代码

  1. function ArrayData () {
  2. let ret = []
  3. this.times = 0 // 统计执行次数
  4. this.push = (item) => {
  5. ret.push(item)
  6. }
  7. this.toString = () => {
  8. return ret.join()
  9. }
  10. }
  11. const arr = [34, 11, 45, 22, 31, 99, 68, 54]
冒泡排序

  比较相邻两个数的大小,如果前面的数大于后面,则交换这两个数的位置。要排序n个数字,需要经历n-1次的遍历。

  按照字面要求,我们写出来的代码是这样的

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.bubbleSort = function () {
  4. let length = ret.length;
  5. for (let i = 0; i < length; i++) {
  6. for (let j = 0; j < length - 1; j++) {
  7. this.times++
  8. if (ret[j] > ret[j + 1]) {
  9. [ret[j], ret[j + 1]] = [ret[j + 1], ret[j]]
  10. }
  11. }
  12. }
  13. }
  14. }
  15. let tmp = new ArrayData()
  16. arr.forEach((item) => {
  17. tmp.push(item)
  18. })
  19. tmp.bubbleSort()
  20. console.log(tmp.times) // 56

  显然这种简单粗暴的排序方式有很大的提升空间,比如,我们可以检测每次排序,如果顺序已经排列成功,就没必要执行之后的循环了。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.bubbleSort = function () {
  4. let length = ret.length;
  5. for (let i = 0; i < length; i++) {
  6. let change = false
  7. for (let j = 0; j < length - 1; j++) {
  8. this.times++Ï
  9. if (ret[j] > ret[j + 1]) {
  10. [ret[j], ret[j + 1]] = [ret[j + 1], ret[j]]
  11. change = true
  12. }
  13. }
  14. if (!change) {
  15. break
  16. }
  17. }
  18. }
  19. }
  20. let tmp = new ArrayData()
  21. arr.forEach((item) => {
  22. tmp.push(item)
  23. })
  24. tmp.bubbleSort()
  25. console.log(tmp.times) // 21

  其实还是有优化的空间的。举个例子,假设一共8个数,第一轮循环,会把最大的数冒泡排到第8位,第二轮循环,会把第二大的数排到第7位,所以,本轮循坏其实没必要考虑最后一位了。同理,下一轮循环就不需要考虑后两位。改进后的代码如下:

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.bubbleSort = function () {
  4. let length = ret.length;
  5. for (let i = 0; i < length; i++) {
  6. let change = false
  7. for (let j = 0; j < length - 1 - i; j++) {
  8. this.times++
  9. if (ret[j] > ret[j + 1]) {
  10. [ret[j], ret[j + 1]] = [ret[j + 1], ret[j]]
  11. change = true
  12. }
  13. }
  14. if (!change) {
  15. break
  16. }
  17. }
  18. }
  19. }
  20. let tmp = new ArrayData()
  21. arr.forEach((item) => {
  22. tmp.push(item)
  23. })
  24. tmp.bubbleSort()
  25. console.log(tmp.times) // 18
选择排序

  遍历数组,找出最小的数排在第一位,第二轮循环找出第二小的数放在第二位,以此类推。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.selectionSort = function () {
  4. let length = ret.length
  5. for (let i = 0; i < length - 1; i++) {
  6. let minIndex = i
  7. for (let j = i; j < length; j++) {
  8. if (ret[j] < ret[minIndex]) {
  9. minIndex = j
  10. }
  11. }
  12. if (i !== minIndex) {
  13. [ret[i], ret[minIndex]] = [ret[minIndex], ret[i]]
  14. }
  15. }
  16. }
  17. }
  18. let tmp = new ArrayData()
  19. arr.forEach((item) => {
  20. tmp.push(item)
  21. })
  22. tmp.selectionSort()
插入排序

  把数组分成前后两部分,前面的一部分是排好序的,然后分别把后面一部分的数字插入到前面排好序的数组中。所以,刚开始时设定第一个元素为排好序的部分,分别把后面的数字插入进来。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.insertSort = function () {
  4. let length = ret.length
  5. let j
  6. for (let i = 1; i < length; i++) {
  7. let currentNumber = ret[i]
  8. for (j = i - 1; j >= 0 && ret[j] > currentNumber; j--) {
  9. ret[j + 1] = ret[j]
  10. }
  11. ret[j + 1] = currentNumber
  12. }
  13. }
  14. }
  15. let tmp = new ArrayData()
  16. arr.forEach((item) => {
  17. tmp.push(item)
  18. })
  19. tmp.insertSort()
快速排序

  选一个数作为基准数,遍历数列,把比它
放到他前面,比他小的放到他后面,然后再对基准数前后的数列递归上述操作,直到数列长度为1。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.quickSort = function () {
  4. quick(ret, 0, ret.length - 1);
  5. function quick(array, left, right) {
  6. let index
  7. if (array.length > 1) {
  8. index = partition(array, left, right)
  9. if (left < index - 1) {
  10. quick(array, left, index - 1)
  11. }
  12. if (right > index) {
  13. quick(array, index, right)
  14. }
  15. }
  16. return array
  17. }
  18. function partition(array, left, right) {
  19. let pivot = array[Math.floor((right + left) / 2)],
  20. i = left,
  21. j = right;
  22. while (i <= j) {
  23. while (array[i] < pivot) {
  24. i++
  25. }
  26. while (array[j] > pivot) {
  27. j--
  28. }
  29. if (i <= j) {
  30. swap(array, i, j);
  31. i++;
  32. j--;
  33. }
  34. }
  35. return i
  36. }
  37. function swap(array, i, j) {
  38. [array[i], array[j]] = [array[j], array[i]]
  39. }
  40. }
  41. }
  42. let tmp = new ArrayData()
  43. arr.forEach((item) => {
  44. tmp.push(item)
  45. })
  46. tmp.quickSort()

  一句话实现快速排序。选择第一个元素作为参考元素,利用filter把数组分成大于参考元素和小于参考元素的两个数组,并对这两个数组递归调用快排函数。

</>复制代码

  1. function quickSort(arr) {
  2. return arr.length <= 1 ? arr : quickSort(arr.slice(1).filter((item) => item <= arr[0])).concat(arr[0], quickSort(arr.slice(1).filter((item) => item > arr[0])))
  3. }
希尔排序

  希尔排序是把数组按下标的一定增量分组,对每组进行插入排,随着增量逐渐减少,每个数组的长度越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.shellSort = function () {
  4. let length = ret.length
  5. for (let step = Math.floor(length / 2); step > 0; step = Math.floor(step / 2)) {
  6. for (let i = 0; i < step; i++) {
  7. shellInsertSort(i, step)
  8. }
  9. }
  10. function shellInsertSort(index, step) {
  11. let length = ret.length
  12. let j
  13. for (let i = index; i < length; i += step) {
  14. let currentNumber = ret[i]
  15. for (j = i - step; j >= 0 && ret[j] > currentNumber; j -= step) {
  16. ret[j + step] = ret[j]
  17. }
  18. ret[j + step] = currentNumber
  19. }
  20. }
  21. }
  22. }
  23. let tmp = new ArrayData()
  24. arr.forEach((item) => {
  25. tmp.push(item)
  26. })
  27. tmp.shellSort()
归并排序

  归并排序采用分治的思想,将已有序的子序列合并,得到完全有序的序列。所以我们把数列分割成不超过两个元素的数组,然后将其合并。

</>复制代码

  1. function ArrayData () {
  2. // ......
  3. this.mergeSort = function () {
  4. ret = mergeSortFun(ret)
  5. function mergeSortFun(arr) {
  6. let length = arr.length
  7. if (length <= 1) {
  8. return arr
  9. }
  10. let mid = Math.floor(length / 2),
  11. left = arr.slice(0, mid),
  12. right = arr.slice(mid, length)
  13. return mengeConnect(mergeSortFun(left), mergeSortFun(right))
  14. }
  15. function mengeConnect(left, right) {
  16. let
  17. leftIndex = 0,
  18. rightIndex = 0,
  19. result = []
  20. while (leftIndex < left.length && rightIndex < right.length) {
  21. result.push(left[leftIndex] < right[rightIndex] ? left[leftIndex++] : right[rightIndex++])
  22. }
  23. while (leftIndex < left.length) {
  24. result.push(left[leftIndex++])
  25. }
  26. while (rightIndex < right.length) {
  27. result.push(right[rightIndex++])
  28. }
  29. return result
  30. }
  31. }
  32. }
  33. let tmp = new ArrayData()
  34. arr.forEach((item) => {
  35. tmp.push(item)
  36. })
  37. tmp.mergeSort()

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95585.html

相关文章

  • CSS技巧

    摘要:技巧使你的更加专业这是上关于技巧的一篇译文,另外你也可以在本项目看到原文。列举了一些很实用的技巧,比如给空内容的标签添加内容,逗号分隔列表等等。排序算法看源码,把它背下来吧排序算法的封装。主要帮助初学者更好的掌握排序算法的实现。 成为专业程序员路上用到的各种优秀资料、神器及框架 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 Java...

    DangoSky 评论0 收藏0
  • CSS技巧

    摘要:技巧使你的更加专业这是上关于技巧的一篇译文,另外你也可以在本项目看到原文。列举了一些很实用的技巧,比如给空内容的标签添加内容,逗号分隔列表等等。排序算法看源码,把它背下来吧排序算法的封装。主要帮助初学者更好的掌握排序算法的实现。 成为专业程序员路上用到的各种优秀资料、神器及框架 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 Java...

    zgbgx 评论0 收藏0
  • 基本方法笔记 - 收藏集 - 掘金

    摘要:探讨判断横竖屏的最佳实现前端掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 探讨判断横竖屏的最佳实现 - 前端 - 掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 判断横竖屏的实现方法多种多样,本文就此来探讨下目前有哪些实现方法以及其中的优...

    maochunguang 评论0 收藏0
  • JavaScript数据结构和算法

    摘要:栈被称为一种后入先出的数据结构。散列使用的数据结构叫做散列表。这些操作需要求助于其他数据结构,比如下面介绍的二叉查找树。 前言 在过去的几年中,得益于Node.js的兴起,JavaScript越来越广泛地用于服务器端编程。鉴于JavaScript语言已经走出了浏览器,程序员发现他们需要更多传统语言(比如C++和Java)提供的工具。这些工具包括传统的数据结构(如链表,栈,队列,图等),...

    EastWoodYang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<