基数ソートのヒント 1 つ、ソート方法 2 つ、ソートアルゴリズム 3 つ

基数ソートのヒント 1 つ、ソート方法 2 つ、ソートアルゴリズム 3 つ

[[421174]]

基数ソート

コンセプト

基数ソートは、整数をビットごとにソートする非比較整数ソート アルゴリズムです。基数ソートは、カウントソートの制限を打ち破り、広範囲のデータをソートするのに適します。整数は文字列 (名前や日付など) や浮動小数点数を特定の形式で表現することもできるため、基数ソートは整数に限定されません。

2つのソート方法

最下位ビット優先 (LSD): ビットを最下位ビットから最上位ビットの順に並べ替えます。

最上位ビット優先 (MSD): データ ビットを最上位ビットから最下位ビットの順に並べ替えます。

ビット分割のヒント

arr[i] / digit % 10、ここでdigitは10^nです。

LSDソートアルゴリズムの実装

アルゴリズムのアイデア

ビットによるカウントソート

アルゴリズム実装コード

  1. /**
  2. * ビットごとにカウントして並べ替える
  3. * @param arr
  4. * @param 除算
  5. * @戻る 
  6. */
  7. プライベートスタティック  int [] countingSort( int [] arr, int除算) {
  8.  
  9. int [] バケット = 新しいint [10];
  10. ( int i = 0; i < arr.length; i++) {
  11. バケット[arr[i] / 除算 % 10]++;
  12. }
  13.  
  14. ( int i = 1; i < バケット長さ; i++) {
  15. バケット[i] = バケット[i-1] + バケット[i];
  16. }
  17.  
  18. int [] sortArr = 新しいint [arr.length];
  19. ( int i = arr.length - 1; i >= 0; i --) {  
  20. int位置 = バケット[arr[i] / 除算 % 10];
  21. sortArr[位置 - 1] = arr[i];
  22. バケット[arr[i] / 除算 % 10] --;  
  23. }
  24. sortArrを返します
  25. }
  26.  
  27. 公共 静的  int [] radixSort( int [] arr) {
  28. // 配列内の最大値を見つける
  29. 整数 最大値= arr[0];
  30. ( int i = 0; i < arr.length; i++) {
  31. 最大値= Math.max (arr[i]、最大値) ;
  32. }
  33. // ビット順に並べ替え
  34. 整数数字 = 1;
  35. ( int i = 1; i < max ; digit*=10, i = digit) {
  36. arr = countingSort(arr, 数字);
  37. }
  38. arrを返します
  39. }

ソート検証:

  1. 公共 静的void main(String[] args) {
  2. int [] arr = {999,1000,1001,1000,999,1005};
  3. System.out.println ( "ソート前:" + JSON.toJSONString(arr));
  4. int [] sortArr = radixSort(arr);
  5. System.out.println ( "ソート後:" + JSON.toJSONString(sortArr));
  6. }

ソート前: [999, 1000, 1001, 1000, 999, 1005] ソート後: [999, 999, 1000, 1000, 1001, 1005]

MSDソートアルゴリズムの実装

アルゴリズムのアイデア

最上位ビットから始めて、ビットごとにグループ化します。グループ内の要素数が 1 より大きい場合は、最後のビットに達するまで次のビットを再帰的にグループ化し、要素数 = 1 を収集します。

アルゴリズムの手順

  • 最大値を照会し、最高位の桁の基数を取得します。 Math.pow(10, 数字 - 1)
  • ビットごとにグループ化し、バケットに保存します。 groupBucket[位置][groupCounter[位置]] =arr[i];
  • グループ内の要素数が 1 より大きい場合、次のグループ化は再帰的に実行されます。 if (groupBucket[i] > 1) {int[] tmp = msdSort(copyArr, radix / 10);}
  • グループ内の要素数 = 1、要素を収集します。 sortArr[インデックス++] = groupBucket[i][0];

たとえば、配列 [333, 1002, 1001, 1000, 333, 1003, 2000] をソートするには、次の手順に従います。

アルゴリズム実装コード

  1. 公共 静的  int [] ソート( int [] arr){
  2.  
  3. 整数 最大値= arr[0];
  4. ( int i = 0; i < arr.length; i++) {
  5. // 最大値を取得する
  6. 最大値= Math.max (arr[i]、最大値) ;
  7. }
  8.  
  9. // 最大値を取得する
  10. int digit = getDataDigit(最大);
  11. // 最大値のカーディナリティを計算する
  12. int radix = new Double (Math.pow(10, digit - 1)).intValue();
  13. //msd 基数ソート
  14. msdSort(arr, radix)を返します
  15. }
  16.  
  17. /**
  18. * MSD基数ソート
  19. * @param arr
  20. * @param 基数
  21. * @戻る 
  22. */
  23. 公共 静的  int [] msdSort( int [] arr, int基数) {
  24.  
  25. // 単位の桁まで再帰的にグループ化して終了
  26. 基数 <= 0 の場合
  27. arrを返します
  28. }
  29.  
  30. // グループカウンター
  31. int [] groupCounter = 新しいint [10];
  32. // グループバケット
  33. int [][] groupBucket = 新しいint [10][arr.length];
  34. // ソートする配列を走査し、ビットごとにグループ化します
  35. ( int i = 0; i < arr.length; i++) {
  36. // グループ化バケットの位置を計算する
  37. int位置 = arr[i] / 基数 % 10;
  38. // 要素をグループに保存する
  39. groupBucket[位置][groupCounter[位置]] = arr[i];
  40. // 現在のグループ数に 1 を加算
  41. groupCounter[位置]++;
  42. }
  43.  
  44. 整数 インデックス= 0;
  45. int [] sortArr = 新しいint [arr.length];
  46.  
  47. // グループカウンタを走査する
  48. ( int i = 0; i < groupCounter.length; i++) {
  49. // グループ内の要素数 > 1、再帰グループ化
  50. グループカウンタ[i] > 1の場合{
  51. int [] copyArr = Arrays.copyOf(groupBucket[i], groupCounter[i]);
  52. // 再帰的なグループ化
  53. int [] tmp = msdSort(copyArr, 基数 / 10);
  54. // 再帰的にグループ化された要素を収集する
  55. ( int j = 0; j < tmp.length; j++)の場合{
  56. sortArr[インデックス++] = tmp[j];
  57. }
  58. }そうでない場合 (groupCounter[i] == 1) {
  59. // グループ内の要素数が 1 である要素を収集します
  60. sortArr[インデックス++] = groupBucket[i][0];
  61. }
  62. }
  63.  
  64. sortArrを返します
  65. }
  66.  
  67. /**
  68. * データのビット数を取得する
  69. * @param データ
  70. * @戻る 
  71. */
  72. 公共 静的  int getDataDigit( intデータ) {
  73. //整数 インデックス= 0;
  74. // int数字 = 1;
  75. // while (データ / 数字 > 0) {
  76. // 数字 *= 10;
  77. //インデックス++;
  78. // }
  79. //戻る 索引;
  80.  
  81. String.valueOf(data).length()を返します
  82. }

並べ替え結果を確認します。

  1. 公共 静的void main(String[] args) {
  2. int [] arr = {333,1002,1001,1000,333,1003,2000};
  3. System.out.println ( "ソート前:" + JSON.toJSONString(arr));
  4. int [] sortArr = sort(arr);
  5. System.out.println ( "ソート後:" + JSON.toJSONString(sortArr));
  6. }

ソート前: [333, 1002, 1001, 1000, 333, 1003, 2000] ソート後: [333, 333, 1000, 1001, 1002, 1003, 2000]

3 方向セグメンテーション文字クイックソート

アルゴリズムのアイデア

文字列をビットごとに 3 つの間隔に分割します。v 未満の間隔: [lo, lt-1]、v に等しい間隔: [lt, gt]、v より大きい間隔: [gt+1, hi] とし、3 つの間隔を順番に再帰的に分割します。

アルゴリズムの手順

  • v 未満の値に対してウォッチドッグ タイマー lt を定義し、v より大きい値に対してウォッチドッグ タイマー gt を定義します。
  • 3 つの間隔をビット単位の比較で分割します。
  • 3 つの間隔にわたって再帰します。

アルゴリズム実装コード

  1. /**
  2. * 文字列をビットごとに3つの区間に分割する
  3. * 1. v未満の区間: [lo, lt]
  4. * 2. v区間に等しい: [lt,gt]
  5. * 3. v より大きい間隔: [gt+1,hi]
  6. * @param arr
  7. * @param lo
  8. * @param こんにちは
  9. * @param d
  10. */
  11. 公共 静的void sortStr(String[] arr, int lo, int hi, int d){
  12. (高<=低)の場合{
  13. 戻る;
  14. }
  15. // v 未満の値にはゲートキーパー lt を、v より大きい値には gt を定義します。
  16. int lt = lo、gt = hi、i = lo + 1、v = charAt(arr[lo]、d);
  17. (i <= gt){
  18. int t = charAt(arr[i], d);
  19. (t<v)の場合{
  20. 交換(arr、i++、lt++);
  21. }そうでなければ (t > v) {
  22. 交換(arr, i, gt --);  
  23. }それ以外{
  24. 私は++;
  25. }
  26. }
  27.  
  28. // 再帰間隔が v 未満
  29. sortStr(arr, lo, lt - 1, d);
  30. // v の区間を再帰的に等しくする
  31. (v >= 0) の場合 {
  32. sortStr(arr, lt, gt, d + 1);
  33. }
  34. // 再帰が v より大きい
  35. sortStr(arr, gt + 1, hi, d);
  36. }
  37. プライベートスタティック  int charAt(文字列 s, int d) {
  38. d < s.length() の場合 {
  39. s.charAt(d)を返します
  40. }
  41. -1 を返します
  42. }
  43. 公共 静的void exch(String[] arr、 int sourceIdx、 int targetIdx) {
  44. 文字列 tmp = arr[sourceIdx];
  45. arr[ソースID] = arr[ターゲットID];
  46. arr[ターゲットID] = tmp;
  47. }
  48. 検証結果:
  49.  
  50. 公共 静的void main(String[] args) {
  51. String[] a = new String[]{ "by" "air" "she" "shell" "the" "okay" "bump" "shirt" "shells" "sh" "the" "shells" "the" };
  52. System.out.println ( "ソート前:" +JSON.toJSONString(a));
  53. sortStr(a, 0, a.length - 1, 0);
  54. System.out.println ( "ソート後:" +JSON.toJSONString(a));
  55. }

並べ替え前: ["by","air","she","shell","the","okay","bump","shirt","shells","sh","the","shells","the"] 並べ替え後: ["air","bump","by","okay","sh","she","shell","shells","shells","shirt","the","the","the"]

3つのソートアルゴリズムの比較

アルゴリズム

安定していますか?

インプレースソート

実行時間

余分なスペース

利点

リトルエンディアン文字列ソート (LSD)

はい

いいえ

O(n×k) の場合

O(n + k)

より短い固定長文字列

MSD 文字列ソート

はい

いいえ

O(n×k) の場合

O(N+kk)

ランダム文字列

3方向文字列クイックソート

いいえ

はい

O(NlogN)

W+logN

一般的なソートアルゴリズム。特に長い共通接頭辞を持つ文字列の配列に適しています。

要約する

基数ソートは安定した非比較ソートであり、大きなデータ範囲に適しています。

<<:  ついに誰かが自動運転を明確にした

>>:  製造の自動化と効率化の新時代

ブログ    
ブログ    

推薦する

D2C フロントエンド インテリジェンスは「がん」か「特効薬」か?

フロントエンド インテリジェンスには、その名前が示すように、「フロントエンド」と「インテリジェンス」...

...

人工知能は教育にどのような変化をもたらすのでしょうか?

[[441080]]経済観察記者 鄭躍新12月16日、中国教育部元副部長で中国教育国際交流協会会長...

...

スノーフレークアルゴリズムを学ぶのに役立つ記事

[[419666]]序文みなさんこんにちは、パンパンです!これまでは rand と srand を使...

生成AIは私たちの生活をどのように変えるのでしょうか?

ChatGpt と Generative AI が登場してほぼ 1 年が経ち、AI ベースのツール...

IBMがWatson Healthの売却を計画しているが、AI医療はまだ手つかずのままか?

2月19日、IBMがWatson Health部門の売却を検討しており、会社を合理化してハイブリッ...

PyTorch スキルを向上させる 7 つの実用的なヒント (例付き)

[[399124]] PyTorch は、動的ニューラル ネットワーク (if ステートメントや ...

ファーウェイ、セキュリティ業界を洞察から先見へと進化させる2019年スマートセキュリティ事業戦略を発表

[51CTO.comより引用] 2019年8月8日、ファーウェイの2019年スマートセキュリティビジ...

デジタル画像処理における画像操作

画像操作は、コンピュータービジョンと画像処理において重要な役割を果たします。これらの操作は、前処理、...

マスク氏:プログラマーの62%が人工知能が武器化されると考えている

常に人工知能の脅威論を支持してきたシリコンバレーの「鉄人」マスク氏は、今回、プログラマーたちの間で支...

...

AI を活用して経費管理におけるバイアス問題を解決する方法

新型コロナウイルス感染症のパンデミックによってもたらされた変化の中で、組織の業務が在宅勤務からリモー...

...

AIと機械学習の統合アーキテクチャ:インテリジェントな意思決定を可能にする

人工知能 (AI) と機械学習の台頭により、あらゆる業界に大きな変化が起きています。データ量が増加し...