ホームページ > バックエンド開発 > PHPチュートリアル > PHP ソート アルゴリズムの Radix Sort

PHP ソート アルゴリズムの Radix Sort

不言
リリース: 2023-03-24 16:02:02
オリジナル
1909 人が閲覧しました

この記事では主に PHP の基数ソート アルゴリズムを紹介します。PHP の基数ソート アルゴリズムの原理、実装方法、および関連する使用スキルを例の形式で詳細に分析します。 PHP ソート アルゴリズムの Radix Sort について説明した記事です。詳細は次のとおりです:

基数ソートは「Dahua データ構造」には記載されていませんが、8 つの主要なソート アルゴリズムを収集するために、インターネットを通じてこのソート アルゴリズムを自分で学びました。それをあなたと共有しました。

基本的な考え方: 基数ソート(基数ソート)は「分散ソート」(分散ソート)に属し、その名の通り「バケットソート」またはビンソートとも呼ばれるキーの部分情報を使用します。基数ソート方法は安定したソートであり、その時間計算量は O (nlog(r)m) です。ここで、r は取得される基数です。 m はヒープの数です。ある時点では、基数ソート方法が他の安定性ソート方法よりも効率的です。

実際、このアイデアを要約することはできません。例を通して説明してみましょう:

基本的な解決策: PS: ここで紹介する基数ソートでは、LSD (最下位ビットが最初) を使用します。もちろん、MSD (最も重要なものが最初) もあります。Baidu にアクセスして、それらの類似点と相違点を見つけることができます。

今、次の数値があるとします:

2 343 342 1 128 43 4249 814 687 654 3

基数ソートを使用して、小さい値から大きい値へ並べ替えます。

最初のステップは、値を参照するときに、最初に 1 桁の値に従って 0 から 9 までの番号が付けられたバケットに割り当てることです (前から後ろに訪問する場合、以下の手順は同じです):

0 :

1 : 1 2 : 2 342
3 : 343 43 3
4 : 814 654
5 :
6 :
7 : 687
8 : 128
9 : 4249

価値観これらのバケットを再接続して次の順序を形成します:

1 2 342 343 43 3 814 654 687 128 4249

ステップ 3. 10 桁の値に従って、値を参照します (前から順に参照)戻って、次の手順は同じです)、それらを 0 から 9 までの番号が付けられたバケットに割り当てます:

0 : 1 2 3

1 : 8142 : 128
3 :
4 : 342 343 43 4249
5 : 654
6 :
7 :
8 : 687
9 :

4 番目のステップは、これらのバケット内の値を再接続して次のシーケンスを形成することです:

1 2 3 814 128 342 343 43 4249 654 687

ステップ 5: 百の位の値に従って、値を参照するとき (前から後ろに参照する場合、以下の手順は同じです)、値を 0 から 9 までの番号が付いたバケットに割り当てます:

0 : 1 2 3 43

1 : 1282 : 4249
3 : 342 343
4 :
5 :
6 : 654 687
7 :
8 : 814
9 :

6番目のステップは、内の値を再文字列化することです。これらのバケットを接続すると、

1 2 3 43 128 4249 342 343 654 687 814


という順序になります。 。 。 。 。 。誰もが次のステップに進むことができるはずです。実際、6 番目のステップに到達するまでに、ソートされていないものは 4249 個だけ残っています。

上記のステップから、多くのステップは同じなので、1、10、100、、、を制御するだけで済みます。

コードを見てみましょう。

アルゴリズム実装:

//交换函数
function swap(array &$arr,$a,$b){
  $temp = $arr[$a];
  $arr[$a] = $arr[$b];
  $arr[$b] = $temp;
}
//获取数组中的最大数
//就像上面的例子一样,我们最终是否停止算法不过就是看数组中的最大值:4249,它的位数就是循环的次数
function getMax(array $arr){
  $max = 0;
  $length = count($arr);
  for($i = 0;$i < $length;$i ++){
    if($max < $arr[$i]){
      $max = $arr[$i];
    }
  }
  return $max;
}
//获取最大数的位数,最大值的位数就是我们分配桶的次数
function getLoopTimes($maxNum){
  $count = 1;
  $temp = floor($maxNum / 10);
  while($temp != 0){
    $count ++;
    $temp = floor($temp / 10);
  }
  return $count;
}
/**
 * @param array $arr 待排序数组
 * @param $loop 第几次循环标识
 * 该函数只是完成某一位(个位或十位)上的桶排序
 */
function R_Sort(array &$arr,$loop){
  //桶数组,在强类型语言中,这个数组应该声明为[10][count($arr)]
  //第一维是 0-9 十个数
  //第二维这样定义是因为有可能待排序的数组中的所有数的某一位上的只是一样的,这样就全挤在一个桶里面了
  $tempArr = array();
  $count = count($arr);
  //初始化$tempArr数组
  for($i = 0;$i < 10;$i ++){
    $tempArr[$i] = array();
  }
  //求桶的index的除数
  //如798个位桶index=(798/1)%10=8
  //十位桶index=(798/10)%10=9
  //百位桶index=(798/100)%10=7
  //$tempNum为上式中的1、10、100
  $tempNum = (int)pow(10, $loop - 1);
  for($i = 0;$i < $count;$i ++){
    //求出某位上的数字
    $row_index = ($arr[$i] / $tempNum) % 10;
    for($j = 0;$j < $count;$j ++){
      if(@$tempArr[$row_index][$j] == NULL){
        $tempArr[$row_index][$j] = $arr[$i];   //入桶
        break;
      }
    }
  }
  //还原回原数组中
  $k = 0;
  for($i = 0;$i < 10;$i ++){
    for($j = 0;$j < $count;$j ++){
      if(@$tempArr[$i][$j] != NULL){
        $arr[$k ++] = $tempArr[$i][$j];  //出桶
        $tempArr[$i][$j] = NULL;  //避免下次循环的时候污染数据
      }
    }
  }
}
//最终调用的主函数
function RadixSort(array &$arr){
  $max = getMax($arr);
  $loop = getLoopTimes($max);
  //对每一位进行桶分配(1 表示个位,$loop 表示最高位)
  for($i = 1;$i <= $loop;$i ++){
    R_Sort($arr,$i);
  }
}
ログイン後にコピー

呼び出しアルゴリズム:

$arr = array(2, 343, 342, 1, 128, 43, 4249, 814, 687, 654, 3);
RadixSort($arr);
var_dump($arr);
ログイン後にコピー

実行結果:

array(11) {
 [0]=>
 int(1)
 [1]=>
 int(2)
 [2]=>
 int(3)
 [3]=>
 int(43)
 [4]=>
 int(128)
 [5]=>
 int(342)
 [6]=>
 int(343)
 [7]=>
 int(654)
 [8]=>
 int(687)
 [9]=>
 int(814)
 [10]=>
 int(4249)
}
ログイン後にコピー

実際、私はこれらのコードにとても興奮して書きました。今日、ブログを書いているときに、バケットが実際にはキューであることに気づきました。そのため、上記の

が最も適切であり、簡単にするためにここでは使用しません):

R_Sort()函数复杂了,我们使用 array_push() array_shift() 来重写该方法(当然,要模拟队列的话,用 SPL 提供的 splqueue

function R_Sort(array &$arr,$loop){
  $tempArr = array();
  $count = count($arr);
  for($i = 0;$i < 10;$i ++){
    $tempArr[$i] = array();
  }
  //求桶的index的除数
  //如798个位桶index=(798/1)%10=8
  //十位桶index=(798/10)%10=9
  //百位桶index=(798/100)%10=7
  //$tempNum为上式中的1、10、100
  $tempNum = (int)pow(10, $loop - 1);
  for($i = 0;$i < $count;$i ++){
    //求出某位上的数字
    $row_index = ($arr[$i] / $tempNum) % 10;
    //入桶
    array_push($tempArr[$row_index],$arr[$i]);
  }
  //还原回原数组中
  $k = 0;
  for($i = 0;$i < 10;$i ++){
    //出桶
    while(count($tempArr[$i]) > 0){
      $arr[$k ++] = array_shift($tempArr[$i]);
    }
  }
}
ログイン後にコピー

基数ソート方法は次のとおりです。安定したソートとその時間 複雑さは

O (nlog(r)m)

です。ここで、r は基数、m はヒープの数です。

関連する推奨事項:

PHP ソート アルゴリズム クイック ソート (クイック ソート) とその最適化

PHP ソート アルゴリズム マージ ソート (マージ ソート)

PHP ソート アルゴリズム バブル ソート (バブル ソート)

以上がPHP ソート アルゴリズムの Radix Sortの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート