可视化太酷辽!一文了解排序和搜索算法在前端中的应用

在这里插入图片描述

一文了解排序和搜索算法在前端中的应用

  • ⏳序言
  • 🧭一、文章结构抢先知
  • ⌚二、排序和搜索
    • 1、定义
    • 2、JS中的排序和搜索
  • ⏰三、排序算法
    • 1、冒泡排序💡
      • (1)定义
      • (2)实现思路
      • (3)图例
      • (4)代码实现
    • 2、选择排序💡
      • (1)定义
      • (2)实现思路
      • (3)图例
      • (4)代码实现
    • 3、插入排序💡
      • (1)定义
      • (2)实现思路
      • (3)图例
      • (4)代码实现
    • 4、归并排序💡
      • (1)定义
      • (2)实现思路
      • (3)图例
      • (4)代码实现
    • 5、快速排序💡
      • (1)定义
      • (2)实现思路
      • (3)图例
      • (4)代码实现
  • ⏲️四、搜索算法
    • 1、顺序搜索💡
      • (1)定义
      • (2)实现思路
      • (3)代码实现
    • 2、二分搜索💡
      • (1)定义
      • (2)实现思路
      • (3)代码实现
  • ⏱️五、leetcode经典题目解析
    • 1、leetcode21合并两个有序链表(简单)
    • 2、leetcode374猜数字大小(简单)
  • 🕙六、结束语
  • 🐣彩蛋 One More Thing
    • 🏷️往期推荐
    • 🏷️网站推荐
    • 🏷️番外篇

⏳序言

前面的文章中讲解了各种数据结构,那么今天,顺着数据结构与算法这个话题,我们来谈谈算法。算法一般分为两种,一种是排序算法,另一种是搜索算法。

在今天的文章中,将概括排序和搜索在 js 中的应用,同时讲解常见的5种排序算法,分别是:冒泡排序、选择排序、插入排序、归并排序和快速排序。以及常见的两种搜索算法:顺序搜索和二分搜索。

一起来学习吧~🧐

🧭一、文章结构抢先知

在文章开讲之前,我们先用一张思维导图,来辅助大家了解文章结构。详情见下图👇

思维导图

了解完思维导图后,接下来开始进入本文的讲解~

⌚二、排序和搜索

1、定义

  • 排序: 所谓排序,就是把某个乱序的数组变为升序或降序的数组。
  • 搜索: 所谓搜索,就是找出数组中某个元素的下标

2、JS中的排序和搜索

  • JS 中的排序:数组的 sort() 方法。
  • JS 中的搜索:数组中的 indexOf() 方法。

⏰三、排序算法

1、冒泡排序💡

(1)定义

冒泡排序,即比较相邻的两个元素。如果第一个比第二个大,就左右交换它们两个,依次进行n轮。

(2)实现思路

  • 比较所有相邻元素,如果第一个比第二个大,则交换它们。
  • 一轮下来,可以保证最后一个数是最大的。
  • 执行n - 1轮,就可以完成排序。

(3)图例

下面用一个视频来演示冒泡排序的全过程。详情见下图👇

数据结构与算法之冒泡排序

(4)代码实现

/*** @description 冒泡排序*/Array.prototype.bubbleSort = function(){for(let i = 0; i < this.length - 1; i++){for(let j = 0; j < this.length - 1 - i; j++){if(this[j] > this[j + 1]){const temp = this[j];this[j] = this[j + 1];this[j + 1] = temp;}}}
}const arr = [5, 4, 3, 2, 1];
arr.bubbleSort();
console.log(arr); //[1, 2, 3, 4, 5]

2、选择排序💡

(1)定义

选择排序,即在要排序的一组数中,选出最小的数与第一个位置的数交换;然后再剩下的数当中再找最小的数与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

(2)实现思路

  • 找到数组中的最小值,选中它并将其放在第一位。
  • 接着找到第二小的值,选中它并将其放置在第二位。
  • 以此类推,执行n - 1轮。

(3)图例

下面用一个视频来演示选择排序的全过程。详情见下图👇

数据结构与算法之选择排序

(4)代码实现

/*** @description 选择排序*/Array.prototype.selectSort = function(){for(let i = 0; i < this.length - 1; i++){let indexMin = i;for(let j = i; j < this.length; j++){if(this[j] < this[indexMin]){indexMin = j;}}if(indexMin !== i){const temp = this[i];this[i] = this[indexMin];this[indexMin] = temp;}}
}const arr = [5, 4, 3, 2, 1];
arr.selectSort();
console.log(arr); //[1, 2, 3, 4, 5]

3、插入排序💡

(1)定义

插入排序是一种将指定元素与某个有序区域比较并交换位置的排序算法。

(2)实现思路

  • 从第二个数开始往前比。
  • 比它大就往后排。
  • 以此类推进行到最后一个数。

(3)图例

下面用一个视频来演示插入排序的全过程。详情见下图👇

数据结构与算法之插入排序

(4)代码实现

/*** @description 插入排序*/Array.prototype.insertionSort = function(){for(let i = 1; i < this.length; i++){const temp = this[i];let j = i;while(j > 0){if(this[j - 1] > temp){this[j] = this[j - 1];}else{break;}j -= 1;}this[j] = temp;}
}const arr = [6, 2, 3, 4, 5];
arr.insertionSort();
console.log(arr); // [2, 3, 4, 5, 6]

4、归并排序💡

(1)定义

归并排序的实现是使用了一种分而治之的思想,即将一个数组不断地通过两两分组的方式进行比较,最后知道所有元素都被分到一组里,达到整体有序的目的。

(2)实现思路

  • 划分问题:把序列分成元素个数尽量相等的两半;
  • 递归求解:把两半元素分别排序;
  • 合并问题:把两个有序表合并成一个。

(3)图例

下面用一个视频来演示归并排序的全过程。详情见下图👇

数据结构与算法之归并排序

(4)代码实现

/*** @description 归并排序*/Array.prototype.mergeSort = function(){const rec = (arr) => {if(arr.length === 1){return arr;}const mid = Math.floor(arr.length / 2);const left = arr.slice(0, mid);const right = arr.slice(mid, arr.length);const orderLeft = rec(left);const orderRight = rec(right);const res = [];while(orderLeft.length || orderRight.length){if(orderLeft.length && orderRight.length){res.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight.shift());}else if(orderLeft.length){res.push(orderLeft.shift());}else if(orderRight.length){res.push(orderRight.shift());}}return res;}const res = rec(this);res.forEach((n, i) => { this[i] = n; });return res;
}const arr = [5, 4, 3, 2, 1];
// arr.mergeSort();
console.log(arr.mergeSort()); // [1, 2, 3, 4, 5]

5、快速排序💡

(1)定义

快速排序,即通过一趟排序,将需要排序的数据分割成独立的两部分,其中一部分的所有数据比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

(2)实现思路

  • 分区:从数组中任意选择一个“基准”,所有比基准小的元素放在基准前面,比基准大的元素放在基准的后面。
  • 递归:递归的对基准前后的子数组进行分区。

(3)图例

下面用一个视频来演示快速排序的全过程。详情见下图👇

数据结构与算法之快速排序

(4)代码实现

/*** @description 快速排序*//*** 实现思路:* 1.先选一个元素作为基点pivot;* 2.将其余元素中所有比pivot小的值放在pivot的左边,将所有比pivot大的值放在pivot的右边;* 3.然后分别对pivot左边的所有元素和右边的所有元素,从步骤1开始依次进行排序,直到所有元素完整有序。*/Array.prototype.quickSort = function(){const rec = (arr) => {if(arr.length === 1){return arr;}const left = [];const right = [];const mid = arr[0];for(let i = 1; i < arr.length; i++){if(arr[i] < mid){left.push(arr[i]);}else{right.push(arr[i]);}}return [...rec(left), mid, ...rec(right)];}const res = rec(this);res.forEach((n, i) => {this[i] = n;});return res;
} const arr = [2, 4, 5, 3, 1];
console.log(arr.quickSort()); // [1, 2, 3, 4, 5]

⏲️四、搜索算法

1、顺序搜索💡

(1)定义

顺序搜索是指将每一个数据结构中的元素和我们要找的元素做比较。顺序搜索是最低效的一种搜索算法。

(2)实现思路

  • 遍历数组。
  • 找到跟目标值相等的元素,就返回它的下标。
  • 遍历结束后,如果没有搜索到目标值,就返回-1。

(3)代码实现

/*** @description 顺序搜素*/Array.prototype.sequentialSearch = function(item){for(let i = 0; i < this.length; i++){if(this[i] === item){return i;}}return -1;
}const res = [1 ,2, 3, 4, 5].sequentialSearch(3);console.log(res); // 2

2、二分搜索💡

(1)定义

二分搜索,也称折半搜索,它是一种效率较高的搜索方法。但是,折半搜索要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列

(2)实现思路

  • 从数组的中间元素开始,如果中间元素正好是目标值,则搜索结束。
  • 如果目标值大于或小于中间元素,则在大于或小于中间元素的那一半数组中搜索。

(3)代码实现

/*** @description 二分搜索*/Array.prototype.binarySearch = function(item){let low = 0;let high = this.length - 1;while(low <= high){const mid = Math.floor((low + high) / 2);const element = this[mid];if(element < item){low = mid + 1;}else if(element > item){high = mid - 1;}else{return mid;}}return -1;
}const res = [1, 2, 3, 4, 5].binarySearch(1);
console.log(res); // 0

⏱️五、leetcode经典题目解析

1、leetcode21合并两个有序链表(简单)

(1)题意

附上题目链接:leetcode21合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

输入输出示例:

  • 输入: l1 = [1,2,4], l2 = [1,3,4]
  • 输出: [1,1,2,3,4,4]

(2)解题思路

  • 与归并排序中的合并两个有序数组相似。
  • 将数组替换成链表就能解决此 题。

(3)解题步骤

  • 新建一个新链表,作为返回结果。
  • 用指针遍历两个有序链表,并比较两个链表的当前节点,较小者先接入新链表,并将指针后移一步。
  • 链表遍历结束,返回新链表。

(4)代码实现

/*** Definition for singly-linked list.* function ListNode(val, next) {*     this.val = (val===undefined ? 0 : val)*     this.next = (next===undefined ? null : next)* }*/
/*** @param {ListNode} l1* @param {ListNode} l2* @return {ListNode}*/var mergeTwoLists = function(l1, l2) {const res = new ListNode(0);let p = res;let p1 = l1;let p2 = l2;while(p1 && p2){if(p1.val < p2.val){p.next = p1;p1 = p1.next;}else{p.next = p2;p2 = p2.next;}p = p.next;}if(p1){p.next = p1;}if(p2){p.next = p2;}return res.next;
};

2、leetcode374猜数字大小(简单)

(1)题意

猜数字游戏的规则如下:

每轮游戏,我都会从 1n 随机选择一个数字。 请你猜选出的是哪个数字。

如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。

你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0)

-1:我选出的数字比你猜的数字小 pick < num

1:我选出的数字比你猜的数字大 pick > num

0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num

返回我选出的数字。

输入输出示例:

  • 输入: n = 10, pick = 6
  • 输出: 6

(2)解题思路

  • 二分搜索。
  • 调用guess函数,来判断中间元素是否是目标值。

(3)解题步骤

  • 从数组的中间元素开始,如果中间元素正好是目标值,则搜索过程结束。
  • 如果目标值大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找。

(4)代码实现

/** * Forward declaration of guess API.* @param {number} num   your guess* @return 	            -1 if num is lower than the guess number*			             1 if num is higher than the guess number*                       otherwise return 0* var guess = function(num) {}*//*** @param {number} n* @return {number}*/var guessNumber = function(n) {let low = 1;let high = n;while(low <= high){const mid = Math.floor((low + high) / 2);const res = guess(mid);if(res === 0){return mid;}else if(res === 1){low = mid + 1;}else if(res === -1){high = mid - 1;}}
};

🕙六、结束语

算法在前端中的应用还是蛮广泛的,比如 js 中的 sort()indexOf() 是基于排序和搜索算法来实现的。同时,算法在也是前端面试中的一大必考点,对于不会算法的开发者来说,无形之中与别人的核心竞争力就会被削减了一大半。

本文主要讲解了一些常见的排序和搜索的基础实现,后续大家还可以继续深挖一些其他场景,举一反三,慢慢的理解就会越来越深入了~

到这里,排序和搜索算法的讲解就结束啦!希望对大家有帮助~

如文章有误或有不理解的地方,欢迎小伙伴们评论区留言撒💬

🐣彩蛋 One More Thing

🏷️往期推荐

栈👉栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!

队列👉详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务

链表👉详解链表在前端的应用,顺便再弄懂原型和原型链!

字典和集合👉ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用

树👉一文了解树在前端中的应用,掌握数据结构中树的生命线

图👉太平洋大西洋水流问题如何解决?一文了解图在前端中的应用

堆👉最小堆最大堆了解吗?一文了解堆在前端中的应用

动态规则和分而治之算法👉一文了解分而治之和动态规则算法在前端中的应用

贪心算法和回溯算法👉一文了解贪心算法和回溯算法在前端中的应用

🏷️网站推荐

文章重的可视化动图用到的是 visualgo 网站进行录屏,该网站几乎涵盖了所有数据结构和算法的实现,包括但不限于排序、位掩码、哈希表、二叉堆和循环查找等等动图的功能。戳此链接可直接进入网站体验可视化~

网站推荐

🏷️番外篇

  • 关注公众号星期一研究室,第一时间关注学习干货,更多精选专栏待你解锁~
  • 如果这篇文章对你有用,记得留个脚印jio再走哦~
  • 以上就是本文的全部内容!我们下期见!👋👋👋

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode双指针合集

27. 移除元素 class Solution { public:int removeElement(vector<int>& nums, int val) {/**思路:使用快慢指针&#xff0c;快指针正常往后移动,并将获取的值给慢指针&#xff0c;但是当快指针所指向的值是val的时候慢指针便不再更新;**/ int slowIndex 0;for(…

网络安全逐渐成为程序员的必备技能

大家好&#xff0c;我是Z哥。不知道大家有没有发现。如今&#xff0c;曝光某些知名公司信息泄露的事件频率越来越高。与之对应的&#xff0c;网络安全问题也越来越受到重视。从百度指数摘录了两张图给大家分享下。可以看到&#xff0c;对网络安全相关的信息和关注度在逐渐走高&…

webpack入门核心知识还看不过瘾?速来围观万字入门进阶知识

一文了解webpack入门进阶知识&#x1f93e;‍♀️序言&#x1f3d3;一、Tree Shaking1. 引例阐述2. Tree Shaking配置&#x1f3f8;二、Development和Prodiction模式的区分打包1. 项目打包结构2. 共有配置webpack.common.js3. 开发环境webpack.dev.js4. 生产环境webpack.prod.j…

Power Automate生产现场实例分享回顾

Power Automate生产现场实例分享回顾8月28日&#xff08;周五&#xff09;19&#xff1a;30-21&#xff1a;00&#xff0c;Danfos智慧工厂数字化解决方案高级顾问Helena Wang通过Teams和B站为大家分享了Power Platform开发以及它在工业生产当中的应用。一、什么是低代码开发&am…

万字总结webpack实战案例配置

一文了解webpack中常见实战案例配置&#x1f6f4;序言&#x1f68c;一、Library的打包1. webpack打包库2. 库引用冲突&#x1f68d;二、PWA的打包配置1. PWA是什么2. webpack中的PWA&#x1f68e;三、TypeScript的打包配置1. 引例阐述2. webpack对ts的配置&#xff08;1&#x…

程序员过关斩将--应对高并发系统有没有通用的解决方案呢?

“灵魂拷问&#xff1a;应对高并发系统有没有一些通用的解决方案呢&#xff1f;这些方案解决了什么问题呢&#xff1f;这些方案有那些优势和劣势呢&#xff1f;对性能孜孜不倦的追求是互联网技术不断发展的根本驱动力&#xff0c;从最初的大型机到现在的微型机&#xff0c;在本…

org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the

一:报错 org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement com.wyj.Dao.Bill.BillMapper.getBill. Its likely that neither a Result Type nor a Result Map was specified.二:解决 未在mapper.xml…

.NET5.0 单文件发布打包操作深度剖析

.NET5.0 单文件发布打包操作深度剖析前言随着 .NET5.0 Preview 8 的发布&#xff0c;许多新功能正在被社区成员一一探索&#xff1b;这其中就包含了“单文件发布”这个炫酷的功能&#xff0c;实际上&#xff0c;这也是社区一直以来的呼声&#xff0c;从 WinForm 的 msi 开始&am…

webpack实战之手写一个loader和plugin

webpack实战之编写一个简易的loader和plugin&#x1f514;序言&#x1f3b5;一、如何编写一个Loader1. 碎碎念2. 项目结构3. 业务代码编写&#xff08;1&#xff09;入口文件代码&#xff08;2&#xff09;编写loader&#xff08;3&#xff09;引用loader&#xff08;4&#xf…

手写一个简易bundler打包工具带你了解Webpack原理

用原生js手写一个简易的打包工具bundler&#x1f95d;序言&#x1f349;一、模块分析(入口文件代码分析)1. 项目结构2. 安装第三方依赖3. 业务代码4. 开始打包&#x1f951;二、依赖图谱Dependencies Graph1. 结果分析2. 分析所有模块的依赖关系&#x1f350;三、生成代码1. 逻…

不喜欢 merge 分叉,那就用 rebase 吧

阅读本文大概需要 3 分钟。有些人不喜欢 merge&#xff0c;因为在 merge 之后&#xff0c;commit 历史就会出现分叉&#xff0c;这种分叉再汇合的结构会让有些人觉得混乱而难以管理。如果你不希望 commit 历史出现分叉&#xff0c;可以用 rebase 来代替 merge。rebase &#xf…

你可能对position和z-index有一些误解

一文详解css中的position和z-index&#x1f9c3;序言&#x1f377;一、文章结构抢先知&#x1f378;二、position1. position的取值2. 标准文档流3. 各取值解析&#xff08;1&#xff09;static&#xff08;2&#xff09;relative&#xff08;3&#xff09;absolute&#xff08…

数据结构与算法专题——第九题 外排序

说到排序&#xff0c;大家第一反应基本上是内排序&#xff0c;是的&#xff0c;算法嘛&#xff0c;玩的就是内存&#xff0c;然而内存是有限制的&#xff0c;总有装不下的那一天&#xff0c;此时就可以来玩玩外排序&#xff0c;当然在我看来&#xff0c;外排序考验的是一个程序…

谁动了我的选择器?深入理解CSS选择器优先级

深入理解CSS选择器优先级&#x1f60f;序言&#x1f9d0;文章内容抢先看&#x1f910;一、基础知识1、为什么CSS选择器很强2、CSS选择器的一些基本概念&#xff08;1&#xff09;4种基本概念Ⅰ. 选择器Ⅱ. 选择符Ⅲ. 伪类Ⅳ. 伪元素&#xff08;2&#xff09;CSS选择器的命名空…

leetcode239. 滑动窗口最大值(思路+详解)

一&#xff1a;题目 二:思路 1.这个题不能用优先队列&#xff0c;虽然我们可以通过优先队列得到最大值&#xff0c;但是我们在移动 窗口的时候,便不可以正常的删除元素了 2.虽然不能用优先对列&#xff0c;但是我们依然希望可以得到队首的元素的时候是最大值&#xff0c;同时还…

《ASP.NET Core 与 RESTful API 开发实战》-- (第10章)-- 读书笔记

第 10 章 部署10.1 部署到 IISASP.NET Core 应用程序支持部署到 IIS 中&#xff0c;之后它将作为应用程序的反向代理服务器和负载均衡器&#xff0c;向应用程序中转传入的 HTTP 请求默认情况下&#xff0c;ASP.NET Core 项目的 Program 类使用如下方式创建 WebHostpublic stati…

翠香猕猴桃 和 薄皮核桃,快来下单

猴桃品种有很多&#xff0c;但不是所有的果子都叫翠香。椭圆形&#xff0c;果喙端较尖&#xff0c;黄褐色硬短茸毛&#xff1b;果肉翠绿色&#xff0c;质细多汁&#xff0c;香甜爽口&#xff0c;有芳香味&#xff0c;白色果心。这就是“翠香”&#xff0c;是集酸甜香于一身的猕…

你可能没有听说过 js中的 DOM操作还有这个: HTMLCollection 和 NodeList

一文了解DOM操作中的HTMLCollection和NodeList⛱️序言&#x1f388;一、基础知识1. 定义&#xff08;1&#xff09;HTMLCollection&#xff08;2&#xff09;NodeList2. 属性和方法&#xff08;1&#xff09;HTMLCollection&#xff08;2&#xff09;NodeList&#x1fa81;二、…

leetcode144. 二叉树的前序遍历(递归+迭代)

一:题目 二&#xff1a;上码 1&#xff1a;递归 class Solution { public:void preorder(TreeNode* root,vector<int>&v ) {if(root NULL) return;v.push_back(root->val);preorder(root->left,v);preorder(root->right,v);}vector<int> preorderT…

都说性能调优难?玩转这3款工具,让你秒变“老司机”!

鲁迅说过&#xff1a;菜鸟写业务&#xff0c;老鸟搭架构&#xff0c;高手玩调优。性能调优可谓是食物链顶端的技术&#xff0c;高薪面试必备良品。然而有不少的开发者&#xff0c;工作多年&#xff0c;却对性能调优几乎一无所知&#xff0c;今天就带大家掰扯掰扯&#xff0c;从…