ソートのカウントとマップのいくつかの使用法(c、c ++の説明)

カウントソートとMAP

カウントソート

最初に
例1を使用します

入力:入力n、2行目にn人の学生のスコアを入力、スコアの範囲[0,100]
出力:

この問題でのn個のスコアの並べ替えの安定性を考慮する必要はありません。並べ替えは解決できます。これが1つです。一種の非比較ソート、カウント、ローイング。
上記のコード、C ++の説明

#include<bits/stdc++.h>
using namespace std;
int m[100]={
    
    0};
int main()
{
    
    int n=0,v=0,a=0,i=0,j=0,k=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
    
    
    scanf("%d",&a);//输入每个成绩
    m[a]++;//将每个值出现次数存入m数组,下标为该值
}
for(i=0;i<=100;i++)
{
    
    
    for(j=0;j<m[i];j++)
        printf("%d ",i);//按大小顺序以及出现次数输出
}
    return 0;
}

まず、データ範囲と分布によって決定される時間計算量を見てください。上記のように、データが均等に分散され、サイズが適切である場合、他のどの並べ替えよりもさらに高速です。しかし、データがより広く複雑になると、時間とスペースの浪費が膨大になります。通常の状況では、補助スペースを開く必要がありますが、上記のコードでは必要ありません。
このことから、カウントの使用条件は次のようになります。データ範囲は小さいが、データ量は多い。

例2:

入力:文字で構成された文字列、長さが1000未満
出力:文字列内の文字を辞書式に並べ替え、

Cで記述され上記のコードを出力します。

#include<stdio.h>
#include<string.h>
int main()
{
    
    char s[1000];
int i=0,j=0,l=0,a[128]={
    
    0};
    gets(s);//实际上不建议使用这种输入方式
for(i=0;i<strlen(s);i++)
a[s[i]]++;//虽然开了辅助空间但长度极小
for(i=0;i<128;i++)
for(j=0;j<a[i];j++)
      printf("%c ",i);

    return 0;
}

このような状況に直面した場合、ASCII範囲は128を超えないことが知られており、ソートのカウントの効果は非常に顕著です。
データの範囲が非常に小さい場合、ソートのカウントが優れた効果を発揮することがあります。n番目のアイテムの検索、重複排除、再チェック、その他の問題にも、プレイする余地があり、コードも簡潔で明確です。
しかし、データ範囲が広い場合、上記の方法の時間とスペースの要件も増加します。無駄を回避する方法は、私たちが検討できる最初の最適化の方向です。ここでは、マップを紹介します。

C ++ STL MAP

マップの定義と使用法は自分で検索できます。ここでは一部の操作についてのみ説明します。
単一スコアの値の範囲は0-10 ^ 9、nおよびm <= 100000であると想定しています。

input:nを入力し、mを入力し、2行目にn人の生徒のスコアを入力します
。3行目にm数を入力します。これは、1から始まるこれらの結果の数を求めることを意味します。
output:スコアの最初の出現に対応する数値を出力します。

最初に、これはカウント配列で検索できる問題ですが、配列を直接開くと、10 ^ 9のサイズは直接サイズが大きすぎます
が、マップを開きます。十分なスペースがあります。

int n,m;
map<int,int> f;//声明
int main(){
    
    
int a=0,i=0,j=0,n=0,m=0;
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++){
    
    
		scanf("%d",&a);
		if(!f[a]){
    
    
			f[a]=i;//相同元素只记录第一次出现时序号
		}
	}
	for(i=1;i<=m;i++){
    
    
		scanf("%d",&j);
		if(!f[j]) 
		printf("-1 ");//若不存在
		else 
		printf("%d ",f[j]);
	}
	return 0;
}

map <int、int>を使用して要素ペアを維持します。最初はキータイプ(key)で、2番目は値タイプ(value)です。この質問では、10 ^ 5の数は0-10 ^ 9の値の範囲をカバーできないことがわかっているため、バケットに入るときに配列で多くのスペースを無駄にする必要がありますが、キーと値のペアマップによって提供されるストレージ方法は完璧なソリューションですこの問題を解決するために、単一のデータ範囲(maxV-minV)の長さの配列は必要ありません。検索要素のみの場合、時間とスペースは完全に十分です。 (実際、操作は上記の質問の入力ストリームで完了しています)。
実際、カウントソートはバケット行の最も基本的なケースの1つであり、非比較ソートとして、使用範囲はそれほど大きくありませんが、そのアイデアには改善の余地があり、多くの場合、特殊効果があります。

おすすめ

転載: blog.csdn.net/weixin_43736127/article/details/109610964