ソートアルゴリズム - 基数ソート(C言語)

基数ソートの概念:

基数ソートとは何ですか? ? ? 基数ソートは、高速ソート、マージ、ヒルなどとは異なる一種のソートです。比較や移動を行わずに整数ソートを完了できます。時間計算量は O(K*N)、空間計算量は O(K+M )です。


基数ソートの考え方: 

  • カーディナリティソートは、複数のキーワードのアイデアを利用して単一の論理キーワードをソートする方法です。
  • 基数ソートでは各ビットに従ってバケットが割り当てられますが、どのように理解すればよいでしょうか? ? ? 以下のアニメーションを見てください。0 ~ 9 は割り当てられたバケットです。
  • 一般的な用語では、基数ソートとは、まずデータを分散し、次にデータを再利用することです。以下のアニメーションをご覧ください。

181965eaa5e249518e426b17fcc6d02a.gif


  •  次に、私の思考の流れに従えば、あなたもそれを達成できます。次のコードのように、最初に配列を定義し、次にその番号を調べます。次に、基数ソートを入力します。
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;
}

おすすめ

転載: blog.csdn.net/m0_72165281/article/details/132155522