Rumah hujung hadapan web tutorial js JS中的一些常用基础算法介绍

JS中的一些常用基础算法介绍

Oct 14, 2020 pm 05:33 PM
javascript algoritma

JS中的一些常用基础算法介绍

一个算法只是一个把确定的数据结构的输入转化为一个确定的数据结构的输出的function。算法内在的逻辑决定了如何转换。

基础算法

一、排序

1、冒泡排序

//冒泡排序function bubbleSort(arr) {
  for(var i = 1, len = arr.length; i < len - 1; ++i) { 
     for(var j = 0; j <= len - i; ++j) {    
       if (arr[j] > arr[j + 1]) {     
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
}
Salin selepas log masuk

2、插入排序

//插入排序 过程就像你拿到一副扑克牌然后对它排序一样
function insertionSort(arr) {
  var n = arr.length;  
// 我们认为arr[0]已经被排序,所以i从1开始
  for (var i = 1; i < n; i++) {  
// 取出下一个新元素,在已排序的元素序列中从后向前扫描来与该新元素比较大小
    for (var j = i - 1; j >= 0; j--) {   
        if (arr[i] >= arr[j]) { // 若要从大到小排序,则将该行改为if (arr[i] <= arr[j])即可
        // 如果新元素arr[i] 大于等于 已排序的元素序列的arr[j],
        // 则将arr[i]插入到arr[j]的下一位置,保持序列从小到大的顺序
        arr.splice(j + 1, 0, arr.splice(i, 1)[0]);       
        // 由于序列是从小到大并从后向前扫描的,所以不必再比较下标小于j的值比arr[j]小的值,退出循环
        break;  
      } else if (j === 0) {        
      // arr[j]比已排序序列的元素都要小,将它插入到序列最前面
        arr.splice(j, 0, arr.splice(i, 1)[0]);
      }
    }
  } 
   return arr;
}
Salin selepas log masuk

当目标是升序排序,最好情况是序列本来已经是升序排序,那么只需比较n-1次,时间复杂度O(n)。最坏情况是序列本来是降序排序,那么需比较n(n-1)/2次,时间复杂度O(n^2)。

所以平均来说,插入排序的时间复杂度是O(n^2)。显然,次方级别的时间复杂度代表着插入排序不适合数据特别多的情况,一般来说插入排序适合小数据量的排序。

3、快速排序

//快速排序
function qSort(arr) {
  //声明并初始化左边的数组和右边的数组
  var left = [], right = [];
 //使用数组第一个元素作为基准值
  var base = arr[0];  
 //当数组长度只有1或者为空时,直接返回数组,不需要排序
  if(arr.length <= 1) return arr;  
 //进行遍历
  for(var i = 1, len = arr.length; i < len; i++) {
    if(arr[i] <= base) {    
    //如果小于基准值,push到左边的数组
      left.push(arr[i]);
    } else {    
    //如果大于基准值,push到右边的数组
      right.push(arr[i]);
    }
  }
  //递归并且合并数组元素
  return [...qSort(left), ...[base], ...qSort(right)];
    //return qSort(left).concat([base], qSort(right));}
Salin selepas log masuk

补充:

在这段代码中,我们可以看到,这段代码实现了通过pivot区分左右部分,然后递归的在左右部分继续取pivot排序,实现了快速排序的文本描述,也就是说该的算法实现本质是没有问题的。

虽然这种实现方式非常的易于理解。不过该实现也是有可以改进的空间,在这种实现中,我们发现在函数内定义了left/right两个数组存放临时数据。随着递归的次数增多,会定义并存放越来越多的临时数据,需要Ω(n)的额外储存空间。

因此,像很多算法介绍中,都使用了原地(in-place)分区的版本去实现快速排序,我们先介绍什么是原地分区算法。

原地(in-place)分区算法描述

  • 从数列中挑出一个元素,称为"基准"(pivot),数组第一个元素的位置作为索引。

  • 遍历数组,当数组数字小于或者等于基准值,则将索引位置上的数与该数字进行交换,同时索引+1

  • 将基准值与当前索引位置进行交换

通过以上3个步骤,就将以基准值为中心,数组的左右两侧数字分别比基准值小或者大了。这个时候在递归的原地分区,就可以得到已排序后的数组。

原地分区算法实现

// 交换数组元素位置
function swap(array, i, j) {
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}
function partition(array, left, right) {
    var index = left;
    var pivot = array[right]; // 取最后一个数字当做基准值,这样方便遍历
    for (var i = left; i < right; i++) {
    if (array[i] <= pivot) {
        swap(array, index, i);
        index++;
     }
 }
     swap(array, right, index);
     return index;
     }
Salin selepas log masuk

因为我们需要递归的多次原地分区,同时,又不想额外的地址空间所以,在实现分区算法的时候会有3个参数,分别是原数组array,需要遍历的数组起点left以及需要遍历的数组终点right。

最后返回一个已经排好序的index值用于下次递归,该索引对应的值一定比索引左侧的数组元素小,比所有右侧的数组元素大。

再次基础上我们还是可以进一步的优化分区算法,我们发现 <=pivot可以改为

原地分区版快速排序实现

function quickSort(array) {
    function swap(array, i, j) {
       var temp = array[i];
       array[i] = array[j];
       array[j] = temp;
     }
     function partition(array, left, right) {
        var index = left;
        var pivot = array[right]; // 取最后一个数字当做基准值,这样方便遍历
         for (var i = left; i < right; i++) {
             if (array[i] < pivot) {
                 swap(array, index, i);
                 index++;
           }
      }
      swap(array, right, index);        
      return index;
      }
      function sort(array, left, right) {    
          if (left > right) {        
              return;
        }        
        var storeIndex = partition(array, left, right);
        sort(array, left, storeIndex - 1);
        sort(array, storeIndex + 1, right);
    }

    sort(array, 0, array.length - 1);    
    return array;
}
Salin selepas log masuk

二、字符串

1、回文字符串

//判断回文字符串
function palindrome(str) {
  var reg = /[\W\_]/g;  
  var str0 = str.toLowerCase().replace(reg, "");  
  var str1 = str0.split("").reverse().join("");  
  return str0 === str1;
}
Salin selepas log masuk

2、翻转字符串

function reverseString(str) {
  return str.split("").reverse().join("");
}
Salin selepas log masuk

3、字符串中出现最多次数的字符

function findMaxDuplicateChar(str) {
  var cnt = {}, //用来记录所有的字符的出现频次
      c = &#39;&#39;; //用来记录最大频次的字符
  for (var i = 0; i < str.length; i++) {
      var ci = str[i];    
      if (!cnt[ci]) {
      cnt[ci] = 1;
    } else {
      cnt[ci]++;
    }    
      if (c == &#39;&#39; || cnt[ci] > cnt[c]) {
      c = ci;
    }
  }  
      console.log(cnt)  return c;
}
Salin selepas log masuk

三、数组

1、数组去重

//数组去重
function uniqueArray(arr) {
  var temp = [];  
  for (var i = 0; i < arr.length; i++) {
      if (temp.indexOf(arr[i]) == -1) {
      temp.push(arr[i]);
    }
  } 
      return temp;  
      //or
  return Array.from(new Set(arr));
}
Salin selepas log masuk

四、查找

1、二分查找

//二分查找
function binary_search(arr, l, r, v) {
  if (l > r) {  
    return -1;
  }  
   var m = parseInt((l + r) / 2);  
   if (arr[m] == v) {  
     return m;
  } else if (arr[m] < v) {  
       return binary_search(arr, m+1, r, v);
  } else {   
        return binary_search(arr, l, m-1, v);
  }
}
Salin selepas log masuk

将二分查找运用到之前的插入排序中,形成二分插入排序,据说可以提高效率。但我测试的时候也许是数据量太少,并没有发现太明显的差距。。大家可以自己试验一下~(譬如在函数调用开始和结束使用console.time('插入排序耗时')和console.timeEnd('插入排序耗时'))

五、树的搜索/遍历

1、深度优先搜索

//深搜 非递归实现
function dfs(node) {
  var nodeList = [];  
  if (node) {  
    var stack = [];
    stack.push(node);   
     while(stack.length != 0) {   
        var item = stack.pop();
      nodeList.push(item);      
        var children = item.children;      
        for (var i = children.length-1; i >= 0; i--) {
             stack.push(children[i]);
      }
    }
  }  return nodeList;
} 
//深搜 递归实现
function dfs(node, nodeList) { 
 if (node) {
    nodeList.push(node);    
 var children = node.children;    
 for (var i = 0; i < children.length; i++) {
      dfs(children[i], nodeList);
    }
  }  
 return nodeList;
}
Salin selepas log masuk

2、广度优先搜索

//广搜 非递归实现
function bfs(node) {
    var nodeList = [];    
    if (node != null) {     
       var queue = [];
       queue.unshift(node);        
       while (queue.length != 0) {     
           var item = queue.shift();
            nodeList.push(item);            
           var children = item.children;           
            for (var i = 0; i < children.length; i++)
                queue.push(children[i]);
        }
    }    
        return nodeList;
}
//广搜 递归实现
var i=0;  
//自增标识符
function bfs(node, nodeList) {  
  if (node) {
      nodeList.push(node);      
  if (nodeList.length > 1) {
        bfs(node.nextElementSibling, nodeList); //搜索当前元素的下一个兄弟元素
      }
      node = nodeList[i++];
      bfs(node.firstElementChild, nodeList); //该层元素节点遍历完了,去找下一层的节点遍历
    }    return nodeList;
}
Salin selepas log masuk

高阶函数衍生算法

1、filter去重

filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。也可以这么理解,filter的回调函数把Array的每个元素都处理一遍,处理结果返回false则过滤结果去除该元素,true则留下来

用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。

其实这个筛选函数有多个参数,filter(function (element, index, self),演示一个使用filter去重,像这样:

var r,
arr = [&#39;apple&#39;, &#39;strawberry&#39;, &#39;banana&#39;, &#39;pear&#39;, &#39;apple&#39;, &#39;orange&#39;, &#39;orange&#39;, &#39;strawberry&#39;];
r = arr.filter(function (element, index, self) {   
     return self.indexOf(element) === index;        
 //拿到元素,判断他在数组里第一次出现的位置,是不是和当前位置一样,
 //一样的话返回true,不一样说明重复了,返回false。
});
Salin selepas log masuk

2、sort排序算法

排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个对象呢?

直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。通常规定,对于两个元素x和y,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。

值得注意的例子:

// 看上去正常的结果:
[&#39;Google&#39;, &#39;Apple&#39;, &#39;Microsoft&#39;].sort(); // [&#39;Apple&#39;, &#39;Google&#39;, &#39;Microsoft&#39;];
// apple排在了最后:
[&#39;Google&#39;, &#39;apple&#39;, &#39;Microsoft&#39;].sort(); // [&#39;Google&#39;, &#39;Microsoft", &#39;apple&#39;]
// 无法理解的结果:
[10, 20, 1, 2].sort(); // [1, 10, 2, 20]
Salin selepas log masuk

解释原因

第二个排序把apple排在了最后,是因为字符串根据ASCII码进行排序,而小写字母a的ASCII码在大写字母之后。

第三个排序结果,简单的数字排序都能错。

这是因为Array的sort()方法默认把所有元素先转换为String再排序,结果’10’排在了’2’的前面,因为字符’1’比字符’2’的ASCII码小。

因此我们把结合这个原理:

var arr = [10, 20, 1, 2];
    arr.sort(function (x, y) {    
    if (x < y) {        
        return -1;
        }    
            if (x > y) {         
               return 1;
        }        return 0;
    });   
     console.log(arr); // [1, 2, 10, 20]
Salin selepas log masuk

上面的代码解读一下:传入x,y,如果xy,返回-1,x后面排,如果x=y,无所谓谁排谁前面。

还有一个,sort()方法会直接对Array进行修改,它返回的结果仍是当前Array,一个例子:

var a1 = [&#39;B&#39;, &#39;A&#39;, &#39;C&#39;];var a2 = a1.sort();
    a1; // [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;]
    a2; // [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;]
    a1 === a2; // true, a1和a2是同一对象
Salin selepas log masuk

相关免费学习推荐:js视频教程

Atas ialah kandungan terperinci JS中的一些常用基础算法介绍. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

CLIP-BEVFormer: Selia secara eksplisit struktur BEVFormer untuk meningkatkan prestasi pengesanan ekor panjang CLIP-BEVFormer: Selia secara eksplisit struktur BEVFormer untuk meningkatkan prestasi pengesanan ekor panjang Mar 26, 2024 pm 12:41 PM

Ditulis di atas & pemahaman peribadi penulis: Pada masa ini, dalam keseluruhan sistem pemanduan autonomi, modul persepsi memainkan peranan penting Hanya selepas kenderaan pemanduan autonomi yang memandu di jalan raya memperoleh keputusan persepsi yang tepat melalui modul persepsi boleh Peraturan hiliran dan. modul kawalan dalam sistem pemanduan autonomi membuat pertimbangan dan keputusan tingkah laku yang tepat pada masanya dan betul. Pada masa ini, kereta dengan fungsi pemanduan autonomi biasanya dilengkapi dengan pelbagai penderia maklumat data termasuk penderia kamera pandangan sekeliling, penderia lidar dan penderia radar gelombang milimeter untuk mengumpul maklumat dalam modaliti yang berbeza untuk mencapai tugas persepsi yang tepat. Algoritma persepsi BEV berdasarkan penglihatan tulen digemari oleh industri kerana kos perkakasannya yang rendah dan penggunaan mudah, dan hasil keluarannya boleh digunakan dengan mudah untuk pelbagai tugas hiliran.

Melaksanakan Algoritma Pembelajaran Mesin dalam C++: Cabaran dan Penyelesaian Biasa Melaksanakan Algoritma Pembelajaran Mesin dalam C++: Cabaran dan Penyelesaian Biasa Jun 03, 2024 pm 01:25 PM

Cabaran biasa yang dihadapi oleh algoritma pembelajaran mesin dalam C++ termasuk pengurusan memori, multi-threading, pengoptimuman prestasi dan kebolehselenggaraan. Penyelesaian termasuk menggunakan penunjuk pintar, perpustakaan benang moden, arahan SIMD dan perpustakaan pihak ketiga, serta mengikuti garis panduan gaya pengekodan dan menggunakan alat automasi. Kes praktikal menunjukkan cara menggunakan perpustakaan Eigen untuk melaksanakan algoritma regresi linear, mengurus memori dengan berkesan dan menggunakan operasi matriks berprestasi tinggi.

Terokai prinsip asas dan pemilihan algoritma bagi fungsi isihan C++ Terokai prinsip asas dan pemilihan algoritma bagi fungsi isihan C++ Apr 02, 2024 pm 05:36 PM

Lapisan bawah fungsi C++ sort menggunakan isihan gabungan, kerumitannya ialah O(nlogn), dan menyediakan pilihan algoritma pengisihan yang berbeza, termasuk isihan pantas, isihan timbunan dan isihan stabil.

Bolehkah kecerdasan buatan meramalkan jenayah? Terokai keupayaan CrimeGPT Bolehkah kecerdasan buatan meramalkan jenayah? Terokai keupayaan CrimeGPT Mar 22, 2024 pm 10:10 PM

Konvergensi kecerdasan buatan (AI) dan penguatkuasaan undang-undang membuka kemungkinan baharu untuk pencegahan dan pengesanan jenayah. Keupayaan ramalan kecerdasan buatan digunakan secara meluas dalam sistem seperti CrimeGPT (Teknologi Ramalan Jenayah) untuk meramal aktiviti jenayah. Artikel ini meneroka potensi kecerdasan buatan dalam ramalan jenayah, aplikasi semasanya, cabaran yang dihadapinya dan kemungkinan implikasi etika teknologi tersebut. Kecerdasan Buatan dan Ramalan Jenayah: Asas CrimeGPT menggunakan algoritma pembelajaran mesin untuk menganalisis set data yang besar, mengenal pasti corak yang boleh meramalkan di mana dan bila jenayah mungkin berlaku. Set data ini termasuk statistik jenayah sejarah, maklumat demografi, penunjuk ekonomi, corak cuaca dan banyak lagi. Dengan mengenal pasti trend yang mungkin terlepas oleh penganalisis manusia, kecerdasan buatan boleh memperkasakan agensi penguatkuasaan undang-undang

Algoritma pengesanan yang dipertingkatkan: untuk pengesanan sasaran dalam imej penderiaan jauh optik resolusi tinggi Algoritma pengesanan yang dipertingkatkan: untuk pengesanan sasaran dalam imej penderiaan jauh optik resolusi tinggi Jun 06, 2024 pm 12:33 PM

01Garis prospek Pada masa ini, sukar untuk mencapai keseimbangan yang sesuai antara kecekapan pengesanan dan hasil pengesanan. Kami telah membangunkan algoritma YOLOv5 yang dipertingkatkan untuk pengesanan sasaran dalam imej penderiaan jauh optik resolusi tinggi, menggunakan piramid ciri berbilang lapisan, strategi kepala pengesanan berbilang dan modul perhatian hibrid untuk meningkatkan kesan rangkaian pengesanan sasaran dalam imej penderiaan jauh optik. Menurut set data SIMD, peta algoritma baharu adalah 2.2% lebih baik daripada YOLOv5 dan 8.48% lebih baik daripada YOLOX, mencapai keseimbangan yang lebih baik antara hasil pengesanan dan kelajuan. 02 Latar Belakang & Motivasi Dengan perkembangan pesat teknologi penderiaan jauh, imej penderiaan jauh optik resolusi tinggi telah digunakan untuk menggambarkan banyak objek di permukaan bumi, termasuk pesawat, kereta, bangunan, dll. Pengesanan objek dalam tafsiran imej penderiaan jauh

Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Jan 05, 2024 pm 06:08 PM

Tutorial JavaScript: Bagaimana untuk mendapatkan kod status HTTP, contoh kod khusus diperlukan: Dalam pembangunan web, interaksi data dengan pelayan sering terlibat. Apabila berkomunikasi dengan pelayan, kami selalunya perlu mendapatkan kod status HTTP yang dikembalikan untuk menentukan sama ada operasi itu berjaya dan melaksanakan pemprosesan yang sepadan berdasarkan kod status yang berbeza. Artikel ini akan mengajar anda cara menggunakan JavaScript untuk mendapatkan kod status HTTP dan menyediakan beberapa contoh kod praktikal. Menggunakan XMLHttpRequest

Aplikasi algoritma dalam pembinaan 58 platform potret Aplikasi algoritma dalam pembinaan 58 platform potret May 09, 2024 am 09:01 AM

1. Latar Belakang Pembinaan 58 Portrait Platform Pertama sekali, saya ingin berkongsi dengan anda latar belakang pembinaan 58 Portrait Platform. 1. Pemikiran tradisional platform pemprofilan tradisional tidak lagi mencukupi Membina platform pemprofilan pengguna bergantung pada keupayaan pemodelan gudang data untuk menyepadukan data daripada pelbagai barisan perniagaan untuk membina potret pengguna yang tepat untuk memahami tingkah laku, minat pengguna dan keperluan, dan menyediakan keupayaan sampingan, akhirnya, ia juga perlu mempunyai keupayaan platform data untuk menyimpan, bertanya dan berkongsi data profil pengguna dan menyediakan perkhidmatan profil dengan cekap. Perbezaan utama antara platform pemprofilan perniagaan binaan sendiri dan platform pemprofilan pejabat pertengahan ialah platform pemprofilan binaan sendiri menyediakan satu barisan perniagaan dan boleh disesuaikan atas permintaan platform pertengahan pejabat berkhidmat berbilang barisan perniagaan, mempunyai kompleks pemodelan, dan menyediakan lebih banyak keupayaan umum. 2.58 Potret pengguna latar belakang pembinaan potret di platform tengah 58

Tambah SOTA dalam masa nyata dan meroket! FastOcc: Inferens yang lebih pantas dan algoritma Occ mesra penggunaan sudah tersedia! Tambah SOTA dalam masa nyata dan meroket! FastOcc: Inferens yang lebih pantas dan algoritma Occ mesra penggunaan sudah tersedia! Mar 14, 2024 pm 11:50 PM

Ditulis di atas & Pemahaman peribadi penulis ialah dalam sistem pemanduan autonomi, tugas persepsi adalah komponen penting dalam keseluruhan sistem pemanduan autonomi. Matlamat utama tugas persepsi adalah untuk membolehkan kenderaan autonomi memahami dan melihat elemen persekitaran sekeliling, seperti kenderaan yang memandu di jalan raya, pejalan kaki di tepi jalan, halangan yang dihadapi semasa memandu, tanda lalu lintas di jalan raya, dan sebagainya, dengan itu membantu hiliran. modul Membuat keputusan dan tindakan yang betul dan munasabah. Kenderaan dengan keupayaan pemanduan autonomi biasanya dilengkapi dengan pelbagai jenis penderia pengumpulan maklumat, seperti penderia kamera pandangan sekeliling, penderia lidar, penderia radar gelombang milimeter, dsb., untuk memastikan kenderaan autonomi itu dapat melihat dan memahami persekitaran sekeliling dengan tepat. elemen , membolehkan kenderaan autonomi membuat keputusan yang betul semasa pemanduan autonomi. kepala

See all articles