基数ソートの概念:
基数ソートとは何ですか? ? ? 基数ソートは、高速ソート、マージ、ヒルなどとは異なる一種のソートです。比較や移動を行わずに整数ソートを完了できます。時間計算量は O(K*N)、空間計算量は O(K+M )です。
基数ソートの考え方:
- カーディナリティソートは、複数のキーワードのアイデアを利用して単一の論理キーワードをソートする方法です。
- 基数ソートでは各ビットに従ってバケットが割り当てられますが、どのように理解すればよいでしょうか? ? ? 以下のアニメーションを見てください。0 ~ 9 は割り当てられたバケットです。
- 一般的な用語では、基数ソートとは、まずデータを分散し、次にデータを再利用することです。以下のアニメーションをご覧ください。
- 次に、私の思考の流れに従えば、あなたもそれを達成できます。次のコードのように、最初に配列を定義し、次にその番号を調べます。次に、基数ソートを入力します。
int main()
{
int arr[10] = { 278,109,63,930,589,183,505,269,83,8 };
int n = sizeof(arr) / sizeof(int);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//基数排序
RadixSrot(arr, 0, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
RadixSort 関数の実装:
- このアイデアは、まずデータを配布してから、データをリサイクルすることです。ここでの K はマクロで定義されています。作成した arr 配列は最大でも 100 桁なので、実際には 3 回配布した後でデータを再利用できます。
#define K 3 void RadixSrot(int arr[],int left,int right) //[left,right) { for (int i = 0; i < K; i++) { //分发数据 Distribute(arr, left, right, i); //回收数据 Collect(arr); } }
配信データの実装:
- 配布データでは、各データ配布後に値を受け取るキーを使用します。
- その仕分け状況を毎回お見せしましょう。
- バケットは実際には 0 ~ 9 です。
- 0 1 2 3 4 5 6 7 8 9
- 930 63 505 278 109
- 183 8 589
- 83 269
最初の並べ替え後は次のようになります: 930 63 183 83 505 278 8 109 589 269
- 0 1 2 3 4 5 6 7 8 9
- 505 930 63 278 183
- 008 269 083
- 109 589
2 回目の並べ替え後は 505 008 109 930 63 269 278 183 038 589
3 回目の並べ替え後: 8 63 83 109 183 269 278 505 589 930
- その考え方は次のようなもので、最初に配布されるデータであるため、最初にリサイクルされるため、最悪の場合 (1 桁がすべて同じである場合) を考慮して、1 桁の整数は 10 個の整数のキューを定義しました。配布後、取得した番号を対応するキューに挿入します。次にリサイクルします。最初に配布され、最初に回収され、キューの特性がちょうど満たされるため、キュー内の数値が配列に入れられ、最初のソートが完了します。これらはすべて数百桁であるため、最大は 3 回であるため、上図の for ループを使用して次の並べ替えを完了します。
#define RADIX 10 //定义基数 构造了10个int的队列 queue<int> Q[RADIX]; void Distribute(int arr[],int left,int right,int k) { for (int i = left;i < right; i++) { int key = GetKey(arr[i], k); Q[key].push(arr[i]); } }
int GetKey(int value, int k) { int key = 0; while (k >= 0) { key = value % 10; value /= 10; k--; } return key; }
ソースコードは次のとおりです。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <queue>
using namespace std;
#define K 3
#define RADIX 10
//定义基数 构造了10个int的队列
queue<int> Q[RADIX];
//value : 278
//k =0 的时候 就得到8 k=1 就得到7
int GetKey(int value, int k)
{
int key = 0;
while (k >= 0)
{
key = value % 10;
value /= 10;
k--;
}
return key;
}
//k代表了第几次分发数据
void Distribute(int arr[],int left,int right,int k)
{
for (int i = left;i < right; i++)
{
int key = GetKey(arr[i], k);
Q[key].push(arr[i]);
}
}
void Collect(int arr[])
{
int k = 0;
for (int i = 0; i < RADIX; i++)
{
while (!Q[i].empty())
{
arr[k++] = Q[i].front();
Q[i].pop();
}
}
}
void RadixSrot(int arr[],int left,int right) //[left,right)
{
for (int i = 0; i < K; i++)
{
//分发数据
Distribute(arr, left, right, i);
//回收数据
Collect(arr);
}
}
int main()
{
int arr[10] = { 278,109,63,930,589,183,505,269,83,8 };
int n = sizeof(arr) / sizeof(int);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//基数排序
RadixSrot(arr, 0, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}