可视化太酷辽!一文了解排序和搜索算法在前端中的应用
一文了解排序和搜索算法在前端中的應用
- ?序言
- 🧭一、文章結構搶先知
- ?二、排序和搜索
- 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); // 22、二分搜索💡
(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)題意
猜數字游戲的規則如下:
每輪游戲,我都會從 1 到 n 隨機選擇一個數字。 請你猜選出的是哪個數字。
如果你猜錯了,我會告訴你,你猜測的數字比我選出的數字是大了還是小了。
你可以通過調用一個預先定義好的接口 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再走哦~
- 以上就是本文的全部內容!我們下期見!👋👋👋
總結
以上是生活随笔為你收集整理的可视化太酷辽!一文了解排序和搜索算法在前端中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黄瓜粥的功效与作用、禁忌和食用方法
- 下一篇: 你可能没有听说过 js中的 DOM操作还