成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JS數據結構與算法_排序和搜索算法

開發 前端 算法
這是《學習JavaScript數據結構與算法》的最后一篇博客,也是在面試中常常會被問到的一部分內容:排序和搜索。

 寫在前面

這是《學習JavaScript數據結構與算法》的***一篇博客,也是在面試中常常會被問到的一部分內容:排序和搜索。在這篇博客之前,我每每看到排序頭就是大的,心里想著類似“冒泡排序,兩層遍歷啪啪啪“就完事了,然后再也無心去深入研究排序相關的問題了。如果你也有類似的經歷,希望下面的內容對你有一定幫助

一、準備

在進入正題之前,先準備幾個基礎的函數

(1)交換數組兩個元素 

  1. function swap(arr, sourceIndex, targetIndex) {  
  2.   let temp = arr[sourceIndex];  
  3.   arr[sourceIndex] = arr[targetIndex];  
  4.   arr[targetIndex] = temp;  

(2)快速生成0~N的數組 可點擊查看更多生成方法 

  1. function createArr(length) {  
  2.   return Array.from({length}, (_, i) => i);  

(3)洗牌函數

洗牌函數可快速打亂數組,常見的用法如切換音樂播放順序 

  1. function shuffle(arr) {  
  2.   for (let i = 0; i < arr.length; i += 1) {  
  3.     const rand = Math.floor(Math.random() * (i + 1));  
  4.     if (rand !== i) {  
  5.       swap(arr, i, rand);  
  6.     }  
  7.   }  
  8.   return arr;  

二、排序

常見排序算法可以分為兩大類:

  •  比較類排序:通過比較來決定元素間的相對次序,由于其時間復雜度不能突破O(nlogn),因此也稱為非線性時間比較類排序
  •  非比較類排序:不通過比較來決定元素間的相對次序,它可以突破基于比較排序的時間下界,以線性時間運行,因此也稱為線性時間非比較類排序

在本篇博客中,僅對比較類排序的幾種排序方式進行學習介紹

2.1 冒泡排序

冒泡排序是所有排序算法中最簡單的,通常也是我們學習排序的入門方法。但是,從運行時間的角度來看,冒泡排序是最差的一種排序方式。

核心:比較任何兩個相鄰的項,如果***個比第二個大,則交換它們。元素項向上移動至正確的順序,就好像氣泡升至表面一樣,冒泡排序因而得名

注意:***層遍歷找出剩余元素的***值,至指定位置【依次冒泡出***值】

代碼: 

  1. function bubbleSort(arr) {  
  2.   const len = arr.length;  
  3.   for (let i = 0; i < len; i += 1) {  
  4.     for (let j = 0; j < len - 1 - i; j += 1) {  
  5.       if (arr[j] > arr[j + 1]) { // 比較相鄰元素  
  6.         swap(arr, j, j + 1);  
  7.       }  
  8.     }  
  9.   }  
  10.   return arr;  

2.2 選擇排序

選擇排序是一種原址比較排序算法。

核心:首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小元素,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢

注意:***層遍歷找出剩余元素最小值的索引,然后交換當前位置和最小值索引值【依次找到最小值】

代碼: 

  1. function selectionSort(arr) {  
  2.   const len = arr.length;  
  3.   let minIndex;  
  4.   for (let i = 0; i < len - 1; i += 1) {  
  5.     minIndex = i;  
  6.     for (let j = i + 1; j < len; j += 1) {  
  7.       if (arr[minIndex] > arr[j]) {  
  8.         minIndex = j; // 尋找最小值對應的索引  
  9.       }  
  10.     }  
  11.     if (minIndex === i) continue;  
  12.     swap(arr, minIndex, i);  
  13.   }  
  14.   return arr;  

2.3 插入排序

插入排序的比較順序不同于冒泡排序和選擇排序,插入排序的比較順序是當前項向前比較。

核心:通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入

注意:從第二項開始,依次向前比較,保證當前項以前的序列是順序排列

代碼: 

  1. function insertionSort(arr) {  
  2.   const len = arr.length;  
  3.   let current, pointer;  
  4.   for (let i = 1; i < len; i += 1) {  
  5.     current = arr[i];  
  6.     pointer = i;  
  7.     while(pointer >= 0 && current < arr[pointer - 1]) { // 每次向前比較  
  8.       arr[pointer] = arr[pointer - 1]; // 前一項大于指針項,則向前移動一項  
  9.       pointer -1 
  10.     }  
  11.     arr[pointer] = current; // 指針項還原成當前項  
  12.   }  
  13.   return arr;  

2.4 歸并排序

歸并排序和快速排序相較于上面三種排序算法在實際中更具有可行性(在第四小節我們會通過實踐復雜度來比較這幾種排序算法)

JavaScript的Array類定義了一個sort函數(Array.prototype.sort)用以排序JavaScript數組。ECMAScript沒有定義用哪個排序算法,所以瀏覽器廠商可以自行去實現算法。例如,Mozilla Firefox使用歸并排序作為Array.prototype.sort的實現,而Chrome使用了一個快速排序的變體

歸并排序是一種分治算法。其思想是將原始數組切分成較小的數組,直到每個小數組只有一 個位置,接著將小數組歸并成較大的數組,直到***只有一個排序完畢的大數組。因此需要用到遞歸

核心:歸并排序,拆分成左右兩塊數組,分別排序后合并

注意:遞歸中最小的左右數組比較為單個元素的數組,因此在較上層多個元素對比時,左右兩個數組一定是順序的

代碼: 

  1. function mergeSort(arr) {  
  2.   const len = arr.length;  
  3.   if (len < 2) return arr; // 遞歸的終止條件  
  4.   const middle = Math.floor(len / 2); // 拆分左右數組  
  5.   const left = arr.slice(0, middle);  
  6.   const right = arr.slice(middle);  
  7.   return merge(mergeSort(left), mergeSort(right));  
  8.  
  9. function merge(left, right) { // 將左右兩側比較后進行合并  
  10.   const ret = [];  
  11.   while (left.length && right.length) {  
  12.     if (left[0] > right[0]) {  
  13.       ret.push(right.shift());  
  14.     } else {  
  15.       ret.push(left.shift());  
  16.     }  
  17.   }  
  18.   while (left.length) {  
  19.     ret.push(left.shift());  
  20.   }  
  21.   while (right.length) {  
  22.     ret.push(right.shift());  
  23.   }  
  24.   return ret;  

2.5 快速排序

快速排序也許是最常用的排序算法了。它的復雜度為O(nlogn),且它的性能通常比其他的復 雜度為O(nlogn)的排序算法要好。和歸并排序一樣,快速排序也使用分治的方法,將原始數組分為較小的數組

核心:分治算法,以參考值為界限,將比它小的和大的值拆開

注意:每一次遍歷篩選出比基準點小的值

代碼: 

  1. function quickSort(arr, left = 0right = arr.length - 1) {  
  2.   // left和right默認為數組首尾  
  3.   if (left < right) {  
  4.     let partitionpartitionIndex = partition(arr, left, right);  
  5.     quickSort(arr, left, partitionIndex - 1);  
  6.     quickSort(arr, partitionIndex + 1, right);  
  7.   }  
  8.   return arr;  
  9.  
  10. function partition(arr, left, right) {  
  11.   let pivot = left 
  12.   let index = left + 1; // 滿足比較條件的依次放在分割點后  
  13.   for (let i = index; i <= right; i += 1) {  
  14.     if (arr[i] < arr[pivot]) {  
  15.       swap(arr, i, index);  
  16.       index += 1;  
  17.     }  
  18.   }  
  19.   swap(arr, index - 1, pivot); // 交換順序時,以***一位替換分隔項  
  20.   return index - 1;  

三、搜索算法

3.1 順序搜索

順序或線性搜索是最基本的搜索算法。它的機制是,將每一個數據結構中的元素和我們要找的元素做比較。順序搜索是***效的一種搜索算法。 

  1. function findItem(item, arr) {  
  2.   for (let i = 0; i < arr.length; i += 1) {  
  3.     if (item === arr[i]) {  
  4.       return i;  
  5.     }  
  6.   }  
  7.   return -1;  

3.2 二分搜索

二分搜索要求被搜索的數據結構已排序。以下是該算法遵循的步驟:

  1.     選擇數組的中間值
  2.     如果選中值是待搜索值,那么算法執行完畢
  3.     如果待搜索值比選中值要小,則返回步驟1在選中值左邊的子數組中尋找
  4.     如果待搜索值比選中值要大,則返回步驟1在選中值右邊的子數組中尋找 
  1. function binarySearch(item, arr) {  
  2.   arr = quickSort(arr); // 排序  
  3.   let low = 0 
  4.   let high = arr.length - 1;  
  5.   let mid;  
  6.   while (low <= high) {  
  7.     min = Math.floor((low + high) / 2);  
  8.     if (arr[mid] < item) {  
  9.       low = mid + 1;  
  10.     } else if (arr[mid] > item) {  
  11.       high = mid - 1;  
  12.     } else {  
  13.       return mid;  
  14.     }  
  15.   }  
  16.   return -1;  

四、算法復雜度

4.1 理解大O表示法

大O表示法用于描述算法的性能和復雜程度。分析算法時,時常遇到一下幾類函數

(1)O(1) 

  1. function increment(num){  
  2.     return ++num;  

執行時間和參數無關。因此說,上述函數的復雜度是O(1)(常數)

(2)O(n)

以順序搜索函數為例,查找元素需要遍歷整個數組,直到找到該元素停止。函數執行的總開銷取決于數組元素的個數(數組大小),而且也和搜索的值有關。但是函數復雜度取決于最壞的情況:如果數組大小是10,開銷就是10;如果數組大小是1000,開銷就是1000。這種函數的時間復雜度是O(n),n是(輸入)數組的大小

(3)O(n2)

以冒泡排序為例,在未優化的情況下,每次排序均需進行n*n次執行。時間復雜度為O(n2)

時間復雜度O(n)的代碼只有一層循環,而O(n2)的代碼有雙層嵌套循環。如 果算法有三層遍歷數組的嵌套循環,它的時間復雜度很可能就是O(n3) 

4.2 時間復雜度比較

(1)常用數據結構時間復雜度

(2)排序算法時間復雜度

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2023-04-27 09:13:20

排序算法數據結構

2023-03-10 08:07:39

數據結構算法計數排序

2023-03-02 08:15:13

2023-03-07 08:02:07

數據結構算法數列

2023-03-13 10:08:31

數據結構算法

2023-03-08 08:03:09

數據結構算法歸并排序

2021-04-15 09:36:44

Java數據結構算法

2020-10-21 14:57:04

數據結構算法圖形

2021-07-16 04:57:45

Go算法結構

2021-03-23 08:33:22

Java數據結構算法

2023-10-27 07:04:20

2021-09-04 23:40:53

算法程序員前端

2022-09-24 09:03:55

前端單元測試冒泡排序

2021-11-10 09:17:18

程序員排序算法搜索算法

2023-02-09 07:39:01

2023-03-06 08:10:52

數據結構算法數據

2009-08-03 17:38:12

排序算法C#數據結構

2023-04-14 08:07:20

數據結構算法搜索

2021-04-16 09:40:52

Java數據結構算法

2021-04-22 10:07:45

Java數據結構算法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品美女在线观看 | 中文字幕第7页 | 精品1区2区 | 青青草华人在线视频 | 精国产品一区二区三区 | 日本视频一区二区三区 | 黄色大片网| 日本一区二区高清不卡 | 日韩视频免费看 | 欧美偷偷 | 天天射网站 | 看a网站 | 成人在线看片 | 亚洲乱码一区二区三区在线观看 | 国产综合在线视频 | 国产一区二区三区四区三区四 | 在线精品国产 | 中文字幕在线二区 | 亚洲成av人片在线观看 | 在线播放中文字幕 | 在线视频一区二区三区 | 狠狠操你 | 在线日韩中文字幕 | 日韩黄色小视频 | 少妇性l交大片免费一 | 国产精品一区久久久 | 精品免费视频 | 久久机热| 国产一区91在线 | 亚洲免费一区 | 日韩第一夜| 国产aa | 日韩一区二区三区在线 | 国产羞羞视频在线观看 | 黄网免费看 | 粉嫩一区二区三区四区公司1 | 成人在线一区二区三区 | 亚洲一区久久 | 香蕉二区 | 天天综合久久 | 日韩一区二区免费视频 |