基数ソートのヒント 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

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

要約する

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

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

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

ブログ    
ブログ    
ブログ    

推薦する

自動運転車の分野での課題は何ですか?

テスラが2015年に量産を開始して以来、わずか5、6年で自動運転(インテリジェントアシスト運転とも呼...

世界の AI イベントのトップ 10 を見ると、AI ガバナンスはどのようにして利益を達成し、損害を回避できるのでしょうか?

はじめに:過去数年間を振り返ると、AIに関するネガティブな事件が頻繁に発生しており、政府は一連の政策...

2019年ディープラーニングフレームワークランキング(トップ10からトップ3まで)

【51CTO.comオリジナル記事】 1. 前に書く5Gは2019年上半期の輝く「星」と言えるが、...

人工知能に関する学習体験のまとめ

序文今は知識が急速に反復される時代です。この時代では、次のように感じるかもしれません。「最初から最後...

「新しいインフラ」に注力 - Powerleader がコンピューティングパワーで人工知能を強化

「新インフラ」の7つの主要分野の一つとして、人工知能は政策推進と産業成熟度の大幅な向上の恩恵を受け、...

Pandasの魅力:データ処理から機械学習まで

パート01、 シリーズとデータフレーム: Pandas のコアPandas の 2 つの主要なデータ...

AI産業化が深海域に入る中、コンピューティングパワーのボトルネックをどうやって打破するのか?

AI技術の応用は、一部の業界からあらゆる分野へ、一部のシーンからあらゆるシーンへ、ローカルな探索か...

...

...

AES暗号化アルゴリズムのハードウェア設計方法の簡単な分析

[[356976]]情報セキュリティの分野では、米国は集積回路IPコアの分野で常に独占的地位を占めて...

MIT教授が交通渋滞を解決するアルゴリズムを開発

交通渋滞は車をブロックするだけでなく、人々の心もブロックします。車の窓から頭を出して、目の前に無限に...

Javaコードの効率とアルゴリズム設計を最適化してパフォーマンスを向上

Java 開発では、非効率的なコードや不合理なアルゴリズムにより、プログラムのパフォーマンスが低下す...

驚きですか、それともショックですか?機械学習アルゴリズムの「高エネルギー」な瞬間を評価する

編集者注: 「水は船を運ぶこともできるが、転覆させることもできる。」この古いことわざは、誰もが知って...

人工知能と機械学習の違いは何ですか?

[[210283]]人工知能 (AI) と機械学習 (ML) は、現在非常に注目されている流行語で...

中国チームがボストン・ダイナミクスに対抗する四足歩行ロボットを発表

本日、Yushu Technology は、中国で正式に一般に公開される初の四足歩行ロボットとなる四...