JS及PHP代碼編寫八大排序算法

字號:


    這篇文章主要為大家詳細介紹了JS及PHP代碼編寫八大排序算法的相關(guān)資料,感興趣的小伙伴們可以參考一下
    從學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)開始就接觸各種算法基礎(chǔ),但是自從應(yīng)付完考試之后就再也沒有練習(xí)過,當(dāng)在開發(fā)的時候也是什么時候使用什么時候去查一下,現(xiàn)在在學(xué)習(xí)JavaScript,趁這個時間再把各種基礎(chǔ)算法整理一遍,分別以JS和PHP語法的方式編寫代碼。
    1.冒泡排序
    原理:臨近的數(shù)字兩兩進行比較,按照從小到大或者從大到小的順序進行交換,這樣一趟過去后,最大或最小的數(shù)字被交換到了最后一位,然后再從頭開始進行兩兩比較交換,直到倒數(shù)第二位時結(jié)束
    時間復(fù)雜度:平均情況:O(n2)  最好情況:O(n) 最壞情況:O(n2)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:穩(wěn)定
    //JavaScript語法
     var array = [23,0,32,45,56,75,43,0,34];
     for(var i = 0; i < array.length; i++)
     {
      var isSort = true;
      for(var j = 0; j < array.length - 1 - i; j++)
      {
      if(array[j] > array[j+1])
      {
       isSort = false;
       var temp = array[j];
       array[j] = array[j + 1];
       array[j + 1] = temp;
      }
      }
      if(isSort)
      {
      break;
      }
     }
     console.log(array);
    -----------------------------------------------
    <?php
     $array = [23,0,32,45,56,75,43,0,34];
     for($i = 0; $i < count($array); $i++)
     {
      $isSort = true;
      for($j = 0; $j < count($array) - 1; $j++)
      {
      if($array[$j] > $array[$j+1])
      {
       $isSort = false;
       $temp = $array[$j];
       $array[$j] = $array[$j + 1];
       $array[$j + 1] = $temp;
      }
      }
      if($isSort)
      {
      break;
      }
     }
     var_dump($array);
    ?>
    2.簡單選擇排序
    原理:通過n-i次關(guān)鍵字之間的比較,從n-i+1 個記錄中選擇關(guān)鍵字最小的記錄,并和第i(1<=i<=n)個記錄交換         簡單選擇排序的性能要略優(yōu)于冒泡排序
    時間復(fù)雜度:平均情況:O(n2)  最好情況:O(n) 最壞情況:O(n2)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:不穩(wěn)定
    //JavaScript
      var array = [23,0,32,45,56,75,43,0,34];
      for(var i = 0; i < array.length - 1; i++)
      {
       var pos = i;
       for(var j = i + 1; j < array.length;j++)
       {
        if(array[j] < array[pos])
        {
         pos=j;
        }
       }
       var temp=array[i];
       array[i]=array[pos];
       array[pos]=temp;
      }
      console.log(array);
    ----------------------------------------------
    <?php
      $array = [23,0,32,45,56,75,43,0,34];
      for($i = 0; $i < count($array); $i++)
     {
      $pos = $i;
      for($j = $i + 1;$j < count($array); $j++)
      {
       if($array[$j] < $array[$pos])
       {
        $pos = $j;
       }
      }
      $temp = $array[$i];
      $array[$i] = $array[$pos];
      $array[$pos] = $temp;
     }
     var_dump($array);
    ?>
    3.直接插入排序
    原理:將一個記錄插入到已排序好的有序表中,從而得到一個新,記錄數(shù)增1的有序表。即:先將序列的第1個記錄看成是一個有序的子序列,然后從第2個記錄逐個進行插入,直至整個序列有序為止。             比冒泡法和選擇排序的性能要更好一些
    時間復(fù)雜度:平均情況:O(n2)  最好情況:O(n) 最壞情況:O(n2)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:穩(wěn)定
    //JavaScript
      var array = [23,0,32,45,56,75,43,0,34];
      for(var j = 0;j < array.length;j++) {
       var key = array[j];
       var i = j - 1;
       while (i > -1 && array[i] > key)
       {
        array[i + 1] = array[i];
        i = i - 1;
       }
       array[i + 1] = key;
      }
      console.log(array);
    ------------------------------------------------
    <?php
     //直接插入排序
      $array = [23,0,32,45,56,75,43,0,34];
      for($i = 0; $i < count($array); $i++)
     {
      $key = $array[$i];
      $j= $i - 1;
      while($j > -1 && $array[$j] > $key)
      {
       $array[$j +1] = $array[$j];
       $j = $j - 1;
      }
      $array[$j + 1] = $key;
     }
     var_dump($array);
    ?>
    4.快速排序
    原理:通過一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨立的兩部分,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小,然后再按此方法對這兩部分?jǐn)?shù)據(jù)分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列。
    時間復(fù)雜度:平均情況:O(nlog2n)  最好情況:O(nlog2n) 最壞情況:O(n2)
    空間復(fù)雜度:O(nlog2n)
    穩(wěn)定性:不穩(wěn)定
    //JavaScript 快速排序
        var array = [23,0,32,45,56,75,43,0,34];
        var quickSort = function(arr) {
          if (arr.length <= 1) { return arr; }//檢查數(shù)組的元素個數(shù),如果小于等于1,就返回。
          var pivotIndex = Math.floor(arr.length / 2);//
          var pivot = arr.splice(pivotIndex,1)[0];//選擇"基準(zhǔn)"(pivot),并將其與原數(shù)組分離,
          var left = [];//定義兩個空數(shù)組,用來存放一左一右的兩個子集
          var right = [];
          for (var i = 0; i < arr.length; i++)//遍歷數(shù)組,小于"基準(zhǔn)"的元素放入左邊的子集,大于基準(zhǔn)的元素放入右邊的子集。
          {
            if (arr[i] < pivot) {
              left.push(arr[i]);
            } else {
              right.push(arr[i]);
            }
          }
          return quickSort(left).concat([pivot], quickSort(right));//使用遞歸不斷重復(fù)這個過程,就可以得到排序后的數(shù)組。
        };
        var newArray=quickSort(array);
        console.log(newArray);
    -----------------------------------------------------
    <?php
            $array = [23,0,32,45,56,75,43,0,34];
        function quick_sort($arr) {
          //先判斷是否需要繼續(xù)進行
          $length = count($arr);
          if($length <= 1) {
            return $arr;
          }
          $base_num = $arr[0];//選擇一個標(biāo)尺 選擇第一個元素
          //初始化兩個數(shù)組
          $left_array = array();//小于標(biāo)尺的
          $right_array = array();//大于標(biāo)尺的
          for($i=1; $i<$length; $i++) {      //遍歷 除了標(biāo)尺外的所有元素,按照大小關(guān)系放入兩個數(shù)組內(nèi)
            if($base_num > $arr[$i]) {
              //放入左邊數(shù)組
              $left_array[] = $arr[$i];
            } else {
              //放入右邊
              $right_array[] = $arr[$i];
            }
          }
          //再分別對 左邊 和 右邊的數(shù)組進行相同的排序處理方式
          //遞歸調(diào)用這個函數(shù),并記錄結(jié)果
          $left_array = quick_sort($left_array);
          $right_array = quick_sort($right_array);
          //合并左邊 標(biāo)尺 右邊
          return array_merge($left_array, array($base_num), $right_array);
        }
            $newArray=quick_sort($array);
            var_dump($newArray);
    ?>
    5.希爾排序  
    原理:先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。。
    時間復(fù)雜度:平均情況:O(n√n)  最好情況:O(nlog2n) 最壞情況:O(n2)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:不穩(wěn)定 
    //JavaScript 希爾排序
        var array = [23,0,32,45,56,75,43,0,34];
        var shellSort = function (arr)
        {
          var length=arr.length;
          var h=1;
          while(h<length/3)
          {
            h=3*h+1;//設(shè)置間隔
          }
          while(h>=1)
          {
            for(var i=h; i<length; i++)
            {
              for(var j=i; j>=h && arr[j]<arr[j-h]; j-=h)
              {
                var temp =arr[j-h];
                arr[j-h]=arr[j];
                arr[j]=temp;
              }
            }
            h=(h-1)/3;
          }
          return arr;
        }
        var newArray = shellSort(array);
        console.log(newArray);
    ---------------------------------------------------
    <?php
    //希爾排序
        $array = [23,0,32,45,56,75,43,0,34];
        function shellSort($arr)
        {
          $length=count($arr);
          $h=1;
          while($h<$length/3)
          {
            $h=3*$h+1;//設(shè)置間隔
          }
          while($h>=1)
          {
            for($i=$h; $i<$length; $i++)
            {
              for($j=$i; $j>=$h && $arr[$j]<$arr[$j-$h]; $j-=$h)
              {
                 $temp =$arr[$j-$h];
                 $arr[$j-$h]=$arr[$j];
                 $arr[$j]=$temp;
              }
            }
            $h=($h-1)/3;
          }
          return $arr;
        }
        $newArray = shellSort($array);
        var_dump($newArray)
    ?>
    6.歸并排序
    原理:假設(shè)初始序列含有n個記錄,則可以看成n個有序的子序列,每個子序列的長度為1,然后兩兩歸并,得到(不小于n/2的最小整數(shù))個長度為2或1的有序子序列,再兩兩歸并,...如此重復(fù),直至得到一個長度為n的有序序列為止   
    時間復(fù)雜度:平均情況:O(nlog2n)  最好情況:O(nlog2n) 最壞情況:O(nlog2n)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:穩(wěn)定 
    //JavaScript 歸并排序
        function isArray1(arr){
          if(Object.prototype.toString.call(arr) =='[object Array]'){
            return true;
          }else{
            return false;
          }
        }
        function merge(left,right){
          var result=[];
          if(!isArray1(left)){
            left = [left];
          }
          if(!isArray1(right)){
            right = [right];
          }
          while(left.length > 0&& right.length >0){
            if(left[0]<right[0]){
              result.push(left.shift());
            }else{
              result.push(right.shift());
            }
          }
          return result.concat(left).concat(right);
        }
        function mergeSort(arr){
          var len=arr.length;
          var lim ,work=[];
          var i,j,k;
          if(len ==1){
            return arr;
          }
          for(i=0;i<len;i++){
            work.push(arr[i]);
          }
          work.push([]);
          for(lim=len;lim>1;){//lim為分組長度
            for(j=0,k=0;k<lim;j++,k=k+2){
              work[j]=merge(work[k],work[k+1]);
            }
            work[j]=[];
            lim=Math.floor((lim+1)/2);
          }
          return work[0];
        }
        var array = [23,0,32,45,56,75,43,0,34];
        console.log(mergeSort(array));
    ---------------------------------------------------
    <?php 
       //歸并排序
        function mergeSort(&$arr) {
          $len = count($arr);//求得數(shù)組長度
          mSort($arr, 0, $len-1);
        }
        //實際實現(xiàn)歸并排序的程序
        function mSort(&$arr, $left, $right) {
          if($left < $right) {
            //說明子序列內(nèi)存在多余1個的元素,那么需要拆分,分別排序,合并
            //計算拆分的位置,長度/2 去整
            $center = floor(($left+$right) / 2);
            //遞歸調(diào)用對左邊進行再次排序:
            mSort($arr, $left, $center);
            //遞歸調(diào)用對右邊進行再次排序
            mSort($arr, $center+1, $right);
            //合并排序結(jié)果
            mergeArray($arr, $left, $center, $right);
          }
        }
        //將兩個有序數(shù)組合并成一個有序數(shù)組
        function mergeArray(&$arr, $left, $center, $right) {
          //設(shè)置兩個起始位置標(biāo)記
          $a_i = $left;
          $b_i = $center+1;
          while($a_i<=$center && $b_i<=$right) {
            //當(dāng)數(shù)組A和數(shù)組B都沒有越界時
            if($arr[$a_i] < $arr[$b_i]) {
              $temp[] = $arr[$a_i++];
            } else {
              $temp[] = $arr[$b_i++];
            }
          }
          //判斷 數(shù)組A內(nèi)的元素是否都用完了,沒有的話將其全部插入到C數(shù)組內(nèi):
          while($a_i <= $center) {
            $temp[] = $arr[$a_i++];
          }
          //判斷 數(shù)組B內(nèi)的元素是否都用完了,沒有的話將其全部插入到C數(shù)組內(nèi):
          while($b_i <= $right) {
            $temp[] = $arr[$b_i++];
          }
          //將$arrC內(nèi)排序好的部分,寫入到$arr內(nèi):
          for($i=0, $len=count($temp); $i<$len; $i++) {
            $arr[$left+$i] = $temp[$i];
          }
        }
        $arr = array(23,0,32,45,56,75,43,0,34);
        mergeSort($arr);
        var_dump($arr);
    ?>
    7.堆排序
    原理:堆排序就是利用堆進行排序的方法.基本思想是:將待排序的序列構(gòu)造成一個大頂堆.此時,整個序列的最大值就是堆頂 的根結(jié)點.將它移走(其實就是將其與堆數(shù)組的末尾元素交換, 此時末尾元素就是最大值),然后將剩余的n-1個序列重新構(gòu)造成一個堆,這樣就會得到n個元素的次大值.如此反復(fù)執(zhí)行,便能得到一個有序序列了
    時間復(fù)雜度:平均情況:O(nlog2n)  最好情況:O(nlog2n) 最壞情況:O(nlog2n)
    空間復(fù)雜度:O(1)
    穩(wěn)定性:不穩(wěn)定 
    //JavaScript 堆排序  
       var array = [23,0,32,45,56,75,43,0,34];
       function heapSort(array)
       {
         for (var i = Math.floor(array.length / 2); i >= 0; i--)
         {
           heapAdjust(array, i, array.length - 1); //將數(shù)組array構(gòu)建成一個大頂堆
         }
         for (i = array.length - 1; i >= 0; i--)
         {
           /*把根節(jié)點交換出去*/
           var temp = array[i];
           array[i] = array[0];
           array[0] = temp;
           /*余下的數(shù)組繼續(xù)構(gòu)建成大頂堆*/
           heapAdjust(array, 0, i - 1);
         }
         return array;
       }
       function heapAdjust(array, start, max)
       {
         var temp = array[start];//temp是根節(jié)點的值
         for (var j = 2 * start; j < max; j *= 2)
         {
           if (j < max && array[j] < array[j + 1])
           { //取得較大孩子的下標(biāo)
             ++j;
           }
           if (temp >= array[j])
             break;
           array[start] = array[j];
           start = j;
         }
         array[start] = temp;
       }
       var newArray = heapSort(array);
       console.log(newArray);
    ------------------------------------------------------------
    <?php
      //堆排序
      function heapSort(&$arr) {
        #初始化大頂堆
        initHeap($arr, 0, count($arr) - 1);
        #開始交換首尾節(jié)點,并每次減少一個末尾節(jié)點再調(diào)整堆,直到剩下一個元素
        for($end = count($arr) - 1; $end > 0; $end--) {
          $temp = $arr[0];
          $arr[0] = $arr[$end];
          $arr[$end] = $temp;
          ajustNodes($arr, 0, $end - 1);
        }
      }
      #初始化最大堆,從最后一個非葉子節(jié)點開始,最后一個非葉子節(jié)點編號為 數(shù)組長度/2 向下取整
      function initHeap(&$arr) {
        $len = count($arr);
        for($start = floor($len / 2) - 1; $start >= 0; $start--) {
          ajustNodes($arr, $start, $len - 1);
        }
      }
      #調(diào)整節(jié)點
      #@param $arr  待調(diào)整數(shù)組
      #@param $start  調(diào)整的父節(jié)點坐標(biāo)
      #@param $end  待調(diào)整數(shù)組結(jié)束節(jié)點坐標(biāo)
      function ajustNodes(&$arr, $start, $end) {
        $maxInx = $start;
        $len = $end + 1;  #待調(diào)整部分長度
        $leftChildInx = ($start + 1) * 2 - 1;  #左孩子坐標(biāo)
        $rightChildInx = ($start + 1) * 2;  #右孩子坐標(biāo)
        #如果待調(diào)整部分有左孩子
        if($leftChildInx + 1 <= $len) {
          #獲取最小節(jié)點坐標(biāo)
          if($arr[$maxInx] < $arr[$leftChildInx]) {
            $maxInx = $leftChildInx;
          }
          #如果待調(diào)整部分有右子節(jié)點
          if($rightChildInx + 1 <= $len) {
            if($arr[$maxInx] < $arr[$rightChildInx]) {
              $maxInx = $rightChildInx;
            }
          }
        }
        #交換父節(jié)點和最大節(jié)點
        if($start != $maxInx) {
          $temp = $arr[$start];
          $arr[$start] = $arr[$maxInx];
          $arr[$maxInx] = $temp;
          #如果交換后的子節(jié)點還有子節(jié)點,繼續(xù)調(diào)整
          if(($maxInx + 1) * 2 <= $len) {
            ajustNodes($arr, $maxInx, $end);
          }
        }
      }
      $arr = array(23,0,32,45,56,75,43,0,34);
      heapSort($arr);
      var_dump($arr);
    ?>
    8.基數(shù)排序
    原理:將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個位數(shù)分別比較。由于整數(shù)也可以表達字符串(比如名字或日期)和特定格式的浮點數(shù),所以基數(shù)排序也不是只能使用于整數(shù)?! ?BR>    時間復(fù)雜度:平均情況:O(d(r+n))  最好情況:O(d(n+rd)) 最壞情況:O(d(r+n))   r:關(guān)鍵字的基數(shù)   d:長度  n:關(guān)鍵字個數(shù)
    空間復(fù)雜度:O(rd+n)
    穩(wěn)定性:穩(wěn)定 
    <?php
       #基數(shù)排序,此處僅對正整數(shù)進行排序,至于負數(shù)和浮點數(shù),需要用到補碼,各位有興趣自行研究
       #計數(shù)排序
       #@param $arr 待排序數(shù)組
       #@param $digit_num 根據(jù)第幾位數(shù)進行排序
       function counting_sort(&$arr, $digit_num = false) {
         if ($digit_num !== false) { #如果參數(shù)$digit_num不為空,則根據(jù)元素的第$digit_num位數(shù)進行排序
           for ($i = 0; $i < count($arr); $i++) {
             $arr_temp[$i] = get_specific_digit($arr[$i], $digit_num);
           } 
         } else {
           $arr_temp = $arr;
         }
         $max = max($arr);
         $time_arr = array(); #儲存元素出現(xiàn)次數(shù)的數(shù)組
         #初始化出現(xiàn)次數(shù)數(shù)組
         for ($i = 0; $i <= $max; $i++) {
           $time_arr[$i] = 0;
         }
         #統(tǒng)計每個元素出現(xiàn)次數(shù)
         for ($i = 0; $i < count($arr_temp); $i++) {
           $time_arr[$arr_temp[$i]]++;
         }
         #統(tǒng)計每個元素比其小或相等的元素出現(xiàn)次數(shù)
         for ($i = 0; $i < count($time_arr) - 1; $i++) {
           $time_arr[$i + 1] += $time_arr[$i];
         }
         #利用出現(xiàn)次數(shù)對數(shù)組進行排序
         for($i = count($arr) - 1; $i >= 0; $i--) {
           $sorted_arr[$time_arr[$arr_temp[$i]] - 1] = $arr[$i];
           $time_arr[$arr_temp[$i]]--;
         }
         $arr = $sorted_arr;
         ksort($arr);  #忽略這次對key排序的效率損耗
       }
       #計算某個數(shù)的位數(shù)
       function get_digit($number) {
         $i = 1;
         while ($number >= pow(10, $i)) {
          $i++;
         }
         return $i;
       }
       #獲取某個數(shù)字的從個位算起的第i位數(shù)
       function get_specific_digit($num, $i) {
         if ($num < pow(10, $i - 1)) {
           return 0;
         }
         return floor($num % pow(10, $i) / pow(10, $i - 1));
       }
       #基數(shù)排序,以計數(shù)排序作為子排序過程
       function radix_sort(&$arr) {
         #先求出數(shù)組中最大的位數(shù)
         $max = max($arr);
         $max_digit = get_digit($max);
         for ($i = 1; $i <= $max_digit; $i++) {
           counting_sort($arr, $i);
         }  
       }
       $arr = array(23,0,32,45,56,75,43,0,34);
       radix_sort($arr);
       var_dump($arr);
    ?>
    以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助