js常見算法


常見算法是js實現匯總

/*去重*/

<script>

function delRepeat(arr){

  var newArray=new Array();

  var len=arr.length;

  for(var i=0;i<len;i++){

     for(var j=i+1;j<len;j++)

     {

       if(arr[i]==arr[j])

       {

         ++i;  

       }

     }

    newArray.push(arr[i]);

  }

 return newArray;

}

var arr=new Array("red","red","1","5","2");

alert(delRepeat(arr));

</script>

分類:  計算機基礎

/*二分法*/

又稱為折半查找算法,但是有缺陷就是要求數字是預先排序好的

function binary(items,value){

 var startIndex=0,

     stopIndex=items.length-1,

     midlleIndex=(startIndex+stopIndex)>>>1;

     while(items[middleIndex]!=value && startIndex<stopIndex){

       if(items[middleIndex]>value){

          stopIndex=middleIndex-1;

       }else{

          startIndex=middleIndex+1;

       }

       middleIndex=(startIndex+stopIndex)>>>1;

     }

     return items[middleIndex]!=value ? false:true;

}

 

/*十六進制顏色值的隨機生成*/

function randomColor(){

 var arrHex=["0","2","3","4","5","6","7","8","9","a","b","c","d"],

     strHex="#",

     index;

     for(var i=0;i<6;i++){

      index=Math.round(Math.random()*15);

      strHex+=arrHex[index];

     }

 return strHex;

}

 

/*一個求字符串長度的方法*/

function GetBytes(str){

 var len=str.length,

     bytes=len;

 for(var i=0;i<len;i++){

   if(str.CharCodeAt>255){

     bytes++;

   }

 }

 return bytes;

}

 

/*插入排序*/

所謂的插入排序,就是將序列中的第一個元素看成一個有序的子序列,然后不段向后比較交換比較交換。

---------------------------------華麗麗的分割線-------------------------------------

function insertSort(arr){

  var key;

  for(var j = 1; j < arr.length ; j++){ 

      //排好序的

      var i = j - 1;

      key = arr[j];

      while(i >= 0 && arr[i] > key){  

          arr[i + 1] = arr[i];       

          i --;        

     }

     arr[i + 1] = key;

  }

 return arr;

}

 

 

 

 

/*希爾排序*/

希爾排序,也稱遞減增量排序算法具體描述:http://zh.wikipedia.org/zh/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F

其實說到底也是插入排序的變種

function shellSort(array){

       var stepArr = [1750, 701, 301, 132, 57, 23, 10, 4, 1]; // reverse()在維基上看到這個最優的步長較小數組

        var i = 0;

        var stepArrLength = stepArr.length;

        var len = array.length;

        var len2 =  parseInt(len/2);

        for(;i < stepArrLength; i++){

            if(stepArr[i] > len2){

                continue;

            }

            stepSort(stepArr[i]);

        }

        // 排序一個步長

        function stepSort(step){  

            //console.log(step) 使用的步長統計

            var i = 0, j = 0, f, tem, key;

            var stepLen = len%step > 0 ?  parseInt(len/step) + 1 : len/step; 

            for(;i < step; i++){// 依次循環列

                for(j=1;/*j < stepLen && */step * j + i < len; j++){//依次循環每列的每行

                    tem = f = step * j + i;

                    key = array[f];

 

                    while((tem-=step) >= 0){// 依次向上查找

                        if(array[tem] > key){

                            array[tem+step] = array[tem];

                        }else{

                            break;

                        }

                    }    

                    array[tem + step ] = key;

                }

            }

        }

        return array;

}

 

/*快速排序*/

其實說到底快速排序算法就系對冒泡排序的一種改進,采用的就是算法理論中的分治遞歸的思想,說得明白點,它的做法就是:通過一趟排序將待排序的紀錄分割成兩部分,其中一部分的紀錄值比另外一部分的紀錄值要小,就可以繼續分別對這兩部分紀錄進行排序;不段的遞歸實施上面兩個操作,從而實現紀錄值的排序。

這么說可能不是很清晰,直接上代碼:

<script>

function sort(arr){

   return quickSort(arr,0,arr.length-1);

   function quickSort(arr,l,r){

       if(l<r){

          var mid=arr[parseInt((l+r)/2)],i=l-1,j=r+1;

          while(true){

          //大的放到右邊,小的放到左邊, i與j均為游標

            while(arr[++i]<mid);

            while(arr[--j]>mid);

            if(i>=j)break;//判斷條件

            var temp = arr[i];

            arr[i]=arr[j];

            arr[j]=temp;

          } 

          quickSort(arr,l,i-1);

          quickSort(arr,j+1,r);

       }

      return arr;

   }

}

function main(){

  var list=new Array(49,38,65,97,76,13,27);

  document.write(sort(list).valueOf());

}

main();

</script>

原理圖:

 

/*冒泡法*/

function bullSort(array){

 var temp;

 for(var i=0;i<array.length;i++){

   for(var j=array.length-1;j>i;j--){

     if(array[j]<array[j-1]){

       temp = array[j];

       array[j]=array[j-1];

       array[j-1]=temp;

     }

   }

 }

 return array;

}

 

/*js遞歸實現方案*/

遞歸函數是在一個函數通過調用自身的情況下去解決的:

方式如下:

function factorial(num){

    if(num<=1){

    return 1; 

   }else{

    return num*factorial(num-1);

   }

}

但是這在js里面可能會出現錯誤:

var anotherFactorial = factorial;

factorial=null;

alert(anoterFactorial(4));

因為在調用anoterFactorial時內部的factorial已經不存在了。

解決方法是通過arguments.callee來解決。

如下:

function factorial(num){

  if(num<=1){

   return 1;

  }else{

  return num*arguments.callee(num-1);  

}

var anotherFactorial = factorial;

factorial = null;

alert(anotherFactorial(4));

成功!!!!

}

 

/**js模擬多線程**/

<html><head><title>emu -- 用command模式模擬多線程</title></head><body>

<SCRIPT LANGUAGE="JavaScript">

<!--

if (Array.prototype.shift==null)

Array.prototype.shift = function (){

    var rs = this[0];

    for (var i=1;i<this.length;i++) this[i-1]=this[i]

    this.length=this.length-1

    return rs;

}

if (Array.prototype.push==null)

Array.prototype.push = function (){

    for (var i=0;i<arguments.length;i++) this[this.length]=arguments[i];

    return this.length;

}

 

var commandList = [];

var nAction = 0;//控制每次運行多少個動作

var functionConstructor = function(){}.constructor;

function executeCommands(){

    for (var i=0;i<nAction;i++)

        if (commandList.length>0){

            var command = commandList.shift();

            if (command.constructor == functionConstructor)

                if (command.scheduleTime == null || new Date()-command.scheduleTime>0)

                    command();

                else

                    commandList.push(command);

        }

}

 

function startNewTask(){

    var resultTemp = document.getElementById("sampleResult").cloneNode(true);

    with (resultTemp){

    id="";style.display="block";style.color=(Math.floor(Math.random()* (1<<23)).toString(16)+"00000").substring(0,6);

    }

    document.body.insertBefore(resultTemp,document.body.lastChild);

    commandList.push(function(){simThread(resultTemp,1);});

    nAction++;

}

 

function  simThread(temp,n){

    if (temp.stop) n--;

    else temp.innerHTML = temp.innerHTML - (-n);

    if (n<1000)

        commandList.push(function(){simThread(temp,++n)});

    else{

        var command = function(){document.body.removeChild(temp);;nAction--;};

        command.scheduleTime = new Date()-(-2000);

        commandList.push(command);

    }

}

 

window.onload = function(){setInterval("executeCommands()",1);}

//-->

</SCRIPT>

<button onClick="startNewTask()">開始新線程</button>

 

<BR><BR>

<div id=sampleResult onMouseOver="this.stop=true" onMouseOut="this.stop=false" >0</div>

</body>

</html>

 

 

 

/*選擇法排序*/

選擇法主要有三種:

《1》簡單的選擇排序:簡單的前后交互。

/*簡單選擇法排序*/

其實基本的思想就是從待排序的數組中選擇最小或者最大的,放在起始位置,然后從剩下的數組中選擇最小或者最大的排在這公司數的后面。

http://zh.wikipedia.org/wiki/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F

function selectionSort(data)

{

        var i, j, min, temp , count=data.length;

        for(i = 0; i < count - 1; i++) {

                /* find the minimum */

                min = i;

                for (j = i+1; j < count; j++)

                {    if (data[j] < data[min])

                     { min = j;}

                 }

                /* swap data[i] and data[min] */

                temp = data[i];

                data[i] = data[min];

                data[min] = temp;

        }

   return data;

}

 

《2》樹型排序:又稱錦標賽排序,首先對n個元素進行兩兩比較,然后在其中[n/2]個較小者再進行兩兩比較如此重復直至選出最小的關鍵字的紀錄為止。(可用完全二差樹表示)。缺點:輔助空間需求過大,和“最大值”進行多余比較

《3》堆排序:(不適用於紀錄數較少的文件)

 堆排序算法的過程如下:

1)得到當前序列的最小(大)的元素

2)把這個元素和最后一個元素進行交換,這樣當前的最小(大)的元素就放在了序列的最后,而原先的最后一個元素放到了序列的最前面

3)的交換可能會破壞堆序列的性質(注意此時的序列是除去已經放在最后面的元素),因此需要對序列進行調整,使之滿足於上面堆的性質.

重復上面的過程,直到序列調整完畢為止.

js實現:

<script>

/**

* 堆排序

* @param items 數組

* @return 排序后的數組

*/

   function heapSort(items)

   {

   items = array2heap(items); //將數組轉化為堆

   for(var i = items.length - 1; i >= 0; i--)

   {

      items = swap(items, 0, i); //將根和位置i的數據交換(用於將最大值放在最后面)

      items = moveDown(items, 0, i - 1); //數據交換后恢復堆的屬性

   }

   return items;

   }

   /**

* 將數組轉換為堆

* @param items 數組

* @return 堆

*/

   function array2heap(items)

   {

   for(var i = Math.ceil(items.length / 2) - 1; i >= 0; i--)

   {

      items = moveDown(items, i, items.length - 1); //轉換為堆屬性

   }

   return items;

   }

   /**

* 轉換為堆

* @param items 數組

* @param first 第一個元素

* @param last 最后一個元素

* @return 堆

*/

   function moveDown(items, first, last)

   {

   var largest = 2 * first + 1;

   while(largest <= last)

   {

      if(largest < last && items[largest] < items[largest + 1])

      {

             largest++;

      }

      if(items[first] < items[largest])

      {

             items = swap(items, first, largest); // 交換數據

             first = largest;   //往下移

             largest = 2 * first + 1;

      }

      else

      {

             largest = last + 1; //跳出循環

      }

   }

   return items;

   }

   /**

* 交換數據

* @param items 數組

* @param index1 索引1

* @param index2 索引2

* @return 數據交換后的數組

*/

   function swap(items, index1, index2)

   {

   var tmp = items[index1];

   items[index1] = items[index2];

   items[index2] = tmp;

   return items;

   }

   var a = [345,44,6,454,10,154,3,12,11,4,78,9,0,47,88,9453,4,65,1,5];

   document.write(heapSort(a));

</script>

 

 

 

所謂歸並就是將兩個或者兩個以上的有序表合成一個新的有序表。

遞歸形式的算法在形式上較為簡潔但實用性較差,與快速排序和堆排序相比,歸並排序的最大特點是,它是一種穩定的排序方法。

js實現歸並:

<script>

function MemeryArray(Arr,n, Brr, m)

{      var i, j, k;

       var Crr=new Array(); 

       i = j = k = 0;

       while (i < n && j < m)

       {

              if (Arr[i] < Brr[j])

                     Crr[k++] = Arr[i++];

              else

                     Crr[k++] = Brr[j++];

       }

       while (i < n)

             Crr[k++] = Arr[i++];

       while (j < m)

             Crr[k++] = Brr[j++];

return Crr;

}

var Arr=new Array(45,36,89,75,65);

var Brr=new Array(48,76,59,49,25);

alert(MemeryArray(Arr , Arr.length , Brr , Brr.length));

</script>

歸並排序待續,先睡了:

----------------------------------------------華麗麗的分割線-------------------------------------------------------------------------

歸並排序:

<script>

//將有二個有序數列a[first...mid]和a[mid...last]合並。

function mergearray(Arr,first,mid,last,tempArr)

{

       var i = first, j = mid + 1;

       var m = mid,   n = last;

       var k = 0;

       while (i <= m && j <= n)

       {

              if (Arr[i] < Arr[j])

                     tempArr[k++] = Arr[i++];

              else

                     tempArr[k++] = Arr[j++];

       }

       while (i <= m)

              tempArr[k++] = Arr[i++];

       while (j <= n)

              tempArr[k++] = Arr[j++];

       for (i = 0; i < k; i++)

              Arr[first + i] = tempArr[i];

}

function mergesort(Arr,first,last)

       var tempArr=new Array();

       if (first < last)

       {

         var mid = (first + last)>>>1;

         mergesort(Arr, first, mid, tempArr);    //左邊有序

         mergesort(Arr, mid + 1, last, tempArr);  //右邊有序

         mergearray(Arr, first, mid, last, tempArr);  //再將二個有序數列合並

       }

  return  Arr;

}

var Arr=new Array(1,65,45,98,56,78);

alert(mergesort(Arr,0,Arr.length-1));

</script>

 

 

/*比較兩個字符串的相似性-Levenshtein算法簡介*/

問題與描述:

近似字符串匹配問題

說明:設給定樣本,對於任意文本串,樣本P在文本T中的K-近似匹配(K-approximate match)是指P在T中包含最多K個差異的匹配,這里的差別指:

(1)修改:P與T中對應的字符不同
(2)刪除:T中含有一個未出現在P中的字符
(3)插入:T中不包含出現在P中的一個字符

(也就是編輯距離問題)

例如: 
T: a p r o x i o m a l l y   
P: a p p r o x i m a t l y
經過 1:插入  2:刪除 3:修改
那么 就是一個3-近似問題

事實上,兩個字符串可能有不得出不同的差別數量,所以K-近似匹配要求:
(1)差別數最多為K個
(2)差別數為所有匹配方式下最少的稱為編輯距離
(字符串T到P最少的差別數稱為T和P的編輯距離)

試驗要求:
(1)利用動態規划方法給出兩個字符串編輯距離的算法
(2)分析復雜度
(3)考慮其它方法


Levenshtein Distance 來文史特距離

goodzzp

 LD也叫edit distance,它用來表示2個字符串的相似度,不同於Hamming Distance,它可以用來比較2個長度不同的字符串。LD定義為需要最少多少步基本操作才能讓2個字符串相等,基本操作包含3個:
 1,插入;
 2,刪除;
 3,替換;
 比如,kiteen和sitting之間的距離可以這么計算:
 1,kitten – > sitten, 替換k為s;
 2,sitten – > sittin, 替換e為i;
 3,sittin – > sitting, 增加g;
 所以,其LD為3;
 計算LD的算法表示為:
 int LevenshteinDistance(char str1[1..lenStr1], char str2[1..lenStr2])
 // d is a table with lenStr1+1 rows and lenStr2+1 columns
 declare int d[0..lenStr1, 0..lenStr2]
 // i and j are used to iterate over str1 and str2
 declare int i, j, cost

 for i from 0 to lenStr1
  d[i, 0] := i
 for j from 0 to lenStr2
  d[0, j] := j

 for i from 1 to lenStr1
  for j from 1 to lenStr2
   if str1[i] = str2[j] then cost := 0
         else cost := 1
   d[i, j] := minimum(
         d[i-1, j ] + 1,  // deletion
         d[i , j-1] + 1,  // insertion
         d[i-1, j-1] + cost // substitution
        )

 return d[lenStr1, lenStr2];
 這個算法其實就是一個矩陣的計算:
   k i t t e n
  0 1 2 3 4 5 6
 s 1 1 2 3 4 5 6
 i 2 2 1 2 3 4 5
 t 3 3 2 1 2 3 4
 t 4 4 3 2 1 2 3 
 i 5 5 4 3 2 2 3
 n 6 6 5 4 3 3 2
 g 7 7 6 5 4 4 3
 首先給定第一行和第一列,然后,每個值d[i,j]這樣計算:d[i,j] = min(d[i-1,j]+ 1,d[i,j-1] +1,d[i-1,j-1]+(str1[i] == str2[j]?0:1));
 最后一行,最后一列的那個值就是LD的結果。
 LD(str1,str2) <= max(str1.len,str2.len);

  有人提出了Levenshtein automaton(Levenshtein自動機)來計算和某個字符串距離小於某個值的集合。這樣能夠加快近似字符串的計算過程。見文獻:Klaus U. Schulz, Stoyan Mihov, Fast String Correction with Levenshtein-Automata. International Journal of Document Analysis and Recognition, 5(1):67--85, 2002.

A Guided Tour to Approximate String Matching GONZALO NAVARRO
 這篇文章里面對這個方面(字符串相似)進行了很多描述。其中,包含了動態規划法計算Edit distance的方法。

-------------------------------------------華麗麗的分割線-------------------------------------------------------------------------

js實現:

<script>

//求兩個字符串的相似度,返回差別字符數,Levenshtein Distance算法實現

function Levenshtein_Distance(s,t){

 var n=s.length;// length of s

 var m=t.length;// length of t

 var d=[];// matrix

 var i;// iterates through s

 var j;// iterates through t

 var s_i;// ith character of s

 var t_j;// jth character of t

 var cost;// cost

 // Step 1

 if (n == 0) return m;

 if (m == 0) return n;

 // Step 2

 for (i = 0; i <= n; i++) {

  d[i]=[];

  d[i][0] = i;

 }

 for (j = 0; j <= m; j++) {

  d[0][j] = j;

 }

 // Step 3

 for (i = 1; i <= n; i++) {

  s_i = s.charAt (i - 1);

  // Step 4

  for (j = 1; j <= m; j++) {

   t_j = t.charAt (j - 1);

   // Step 5

   if (s_i == t_j) {

    cost = 0;

   }else{

    cost = 1;

   }

   // Step 6

   d[i][j] = Minimum (d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1] + cost);

  }

 }

 // Step 7

 return d[n][m];

}

//求兩個字符串的相似度,返回相似度百分比

function Levenshtein_Distance_Percent(s,t){

 var l=s.length>t.length?s.length:t.length;

 var d=Levenshtein_Distance(s,t);

 return (1-d/l).toFixed(4);

}

//求三個數字中的最小值

function Minimum(a,b,c){

 return a<b?(a<c?a:c):(b<c?b:c);

}

var str1="ddsddf",str2="xdsfsx";

alert(Levenshtein_Distance_Percent(str1,str2));

</script>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM