Pythonアルゴリズム-カウントソート
21585 ワード
カウントソート 1.アルゴリズム紹介 2.アルゴリズム思想 3.アルゴリズムプロセス 4.pythonコード実装 コード1 最適化後のコード3
1.アルゴリズムの紹介カウントソートは、空間的複雑度および時間的複雑度がいずれもO(n+k)であり、kは整数の範囲である比較に基づいていないソートアルゴリズムである.比較に基づく並べ替えアルゴリズムの時間的複雑さの最小化はO(nlogn)であった. カウントソートの核心は、入力されたデータ値をキーに変換して追加のオープン配列空間に格納することである.線形時間複雑度のソートとして、カウントソートでは、入力されたデータが確定範囲の整数である必要があります. カウントソートは、データ範囲の広い配列に対して、多くの時間とメモリを必要とします.
2.アルゴリズム思想
ソートする配列をA={1,0,3,1,0,1,1}とし、ここで最大値は3、最小値は0とすると、長さは3+1-0=4の配列Cを作成します.次に配列Aを1回走査し、A中の各要素の総数を求め、配列Cの対応ユニットに保持する.例えば0の出現回数が2回であれば、C[0]=2である.1の出現回数が4回であればC[1]=4となる.C=[2,4,0,1]CはAの要素を下にしているので、このようにすると、Aの要素はCの中で自然に秩序化され、その後、0,1,2,3より小さい要素の個数、例えば1より小さい(1を含む)要素は6つ統計される.C,C=[2,6,6,7]を更新し,Cを更新するのはソートの安定性を保証するためである.そして、このCにおけるレコードを各要素のカウントで出力配列Bに展開し、ソートが完了する.すなわち、B[0]からB[1]までが0であり、B[2]からB[5]までが1である.
3.アルゴリズムプロセスは、まず配列の最大値を探し出す.配列のすべての値は0から最大値の間にあるに違いない.例えば、配列の範囲が0-10の場合、配列の値は0-10の11の数の間にあるに違いない. 要素がすべて0の配列を確立し、配列の下に0から最大値と表記し、最大値=10と仮定すると、下図のように 要素
0
0
0
0
0
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
例を挙げて説明するまず20個のランダム整数の値を仮定すると、2,4,2,3,7,1,1,0,0,5,6,9,8,5,7,4,0,10,9,10,10はまずこの無秩序なランダム配列を遍歴し、各要素はその値に従って番号を座席に入れ、配列の下付き要素を+1操作し、例えば、最初の要素が2であれば、下付き2の要素に1: を加える.
要素
0
0
1
0
0
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
2番目の要素が4の場合、下に4と表示されている要素に1を加えます.
要素
0
0
1
0
1
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
3番目の要素が2の場合、下の2の要素に1を加えます.
要素
0
0
2
0
1
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
このように元の配列を巡回し、最終的な結果:
要素
3
2
2
1
2
2
1
2
1
2
2
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
これにより、配列内の各値の出現回数を統計し、この統計結果があれば配列を直接遍歴することができ、配列要素の下付き値を出力し、要素の値は数で、何回出力することができる.
4.pythonコード実装
コード1
コードのいくつかの解釈 enumerate()関数の使用方法:enumerate()関数は、リスト、メタグループ、文字列などの遍歴可能なデータオブジェクトをインデックスシーケンスに結合するために使用され、データとデータの下付き文字をリストします.一般的にforループで使用されます.構文フォーマット:enumerate(sequence,[start=0])パラメータの説明:1.sequence:シーケンス、反復器、または反復をサポートする他のオブジェクト2.start:下付き開始位置 は、enumerateを使用すると、 という結果を得るsequenceが存在することを例示する.
例:
この関数は、下の要素値と対応する下付きインデックスを出力します. for _ in range(maxi+1)の使い方:
出力結果:
ここの下線()プレースホルダで、中身にかかわらず、前の内容を何度もループさせる役割を果たしています.つまりfor_In range(n)の役割は,単にn回のサイクルを繰り返すことである. random.randint(0,10):10 を除く0-10の間の数をランダムに返します.
最適化されたコード3
上のコードは最初から数列の最大値maxiを求め、作成した配列count_arrは、配列の最後の下付きラベルがmaxiであることを保証するためにmaxi+1の長さである.しかし、このコードは厳密ではありません.配列の最小値が50で、最大値が59であれば、上のコードに従って長さが60の配列を作成する必要があります.前の50の数(0-49)はありません.それでは空間を浪費します.だから、配列の長さは、最大値-最小値+1で、配列の最小値をオフセット量とします.例:配列が55,54,59,50,51,52,51,53,56,55の場合、オフセット量=最小値(50)となり、第1の数55の場合、対応する配列の下付きは55-50=5であるべきである
順序付けを安定させるためには、**[50,51,52,...,59]より小さい要素個数、例えば51より小さい要素個数(51を含む)の3つの元のカウント配列を順次統計することができる.
要素の数
1
2
1
1
1
2
1
0
0
1
オフセット後の下付き
0
1
2
3
4
5
6
7
8
9
要素の下付き
50
51
52
53
54
55
56
57
58
59
加算されたカウント配列は
加算の原則は、各要素の出現回数=その前のすべての要素の出現回数+その要素の出現回数
加算回数
1
3
4
5
6
8
9
9
9
10
オフセット後の下付き
0
1
2
3
4
5
6
7
8
9
要素の下付き
50
51
52
53
54
55
56
57
58
59
加算されたカウント配列要素の値は、要素の位置に等しくなります.たとえば、下付き6の要素値は9で、元の数列を表す値56の最終的なソートは、9番目に最適化されたコードです.
ここで私が言った比較はあまり分かりにくいかもしれませんが、カウントソートの詳細については、ここをクリックして確認してください.
カウント・ソートは、最大値と最小値の差が大きくないリストに適用されます.リストの最小値が1で、最大値が1億であれば、カウント・ソートには1億+1の長さのリストを開く必要があります.時間がかかります.
1.アルゴリズムの紹介
2.アルゴリズム思想
ソートする配列をA={1,0,3,1,0,1,1}とし、ここで最大値は3、最小値は0とすると、長さは3+1-0=4の配列Cを作成します.次に配列Aを1回走査し、A中の各要素の総数を求め、配列Cの対応ユニットに保持する.例えば0の出現回数が2回であれば、C[0]=2である.1の出現回数が4回であればC[1]=4となる.C=[2,4,0,1]CはAの要素を下にしているので、このようにすると、Aの要素はCの中で自然に秩序化され、その後、0,1,2,3より小さい要素の個数、例えば1より小さい(1を含む)要素は6つ統計される.C,C=[2,6,6,7]を更新し,Cを更新するのはソートの安定性を保証するためである.そして、このCにおけるレコードを各要素のカウントで出力配列Bに展開し、ソートが完了する.すなわち、B[0]からB[1]までが0であり、B[2]からB[5]までが1である.
3.アルゴリズムプロセス
0
0
0
0
0
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
例を挙げて説明する
要素
0
0
1
0
0
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
2番目の要素が4の場合、下に4と表示されている要素に1を加えます.
要素
0
0
1
0
1
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
3番目の要素が2の場合、下の2の要素に1を加えます.
要素
0
0
2
0
1
0
0
0
0
0
0
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
このように元の配列を巡回し、最終的な結果:
要素
3
2
2
1
2
2
1
2
1
2
2
要素の下付き
0
1
2
3
4
5
6
7
8
9
10
これにより、配列内の各値の出現回数を統計し、この統計結果があれば配列を直接遍歴することができ、配列要素の下付き値を出力し、要素の値は数で、何回出力することができる.
4.pythonコード実装
コード1
def count_sort1(arr):
maxi = max(arr) #
count_arr = [0 for _ in range(maxi + 1)] # 0
#
for value in arr:
count_arr[value] += 1
arr.clear() #
for index, element in enumerate(count_arr): # index:
for i in range(element):
arr.append(index)
def count_sort2(arr):
maxi = max(arr) #
count_arr = [0 for _ in range(maxi + 1)] # 0
#
for value in arr:
count_arr[value] += 1
new_arr = [] #
for i in range(len(count_arr)):
while count_arr[i] != 0:
new_arr.append(i)
count_arr[i] -= 1
return new_arr
import random
numbers = [random.randint(0, 10) for _ in range(20)]
print(numbers)
count_sort1(numbers)
print(numbers)
numbers2=[3,4,5,6,9,5,2,1,2,3,6,8,9,7]
print(count_sort2(numbers2))
コードのいくつかの解釈
1 start sequence[0]
2 start+1 sequence[1]
3 start+2 sequence[2]
...
例:
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
print(i, element)
:
0 one
1 two
2 three
この関数は、下の要素値と対応する下付きインデックスを出力します.
list1 = [0 for _ in range(10)]
print(list)
list2=[2**2 for _ in range(5)]
print(list2)
出力結果:
list1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
list2:[2, 2, 2, 2, 2]
ここの下線()プレースホルダで、中身にかかわらず、前の内容を何度もループさせる役割を果たしています.つまりfor_In range(n)の役割は,単にn回のサイクルを繰り返すことである.
最適化されたコード3
上のコードは最初から数列の最大値maxiを求め、作成した配列count_arrは、配列の最後の下付きラベルがmaxiであることを保証するためにmaxi+1の長さである.しかし、このコードは厳密ではありません.配列の最小値が50で、最大値が59であれば、上のコードに従って長さが60の配列を作成する必要があります.前の50の数(0-49)はありません.それでは空間を浪費します.だから、配列の長さは、最大値-最小値+1で、配列の最小値をオフセット量とします.例:配列が55,54,59,50,51,52,51,53,56,55の場合、オフセット量=最小値(50)となり、第1の数55の場合、対応する配列の下付きは55-50=5であるべきである
順序付けを安定させるためには、**[50,51,52,...,59]より小さい要素個数、例えば51より小さい要素個数(51を含む)の3つの元のカウント配列を順次統計することができる.
要素の数
1
2
1
1
1
2
1
0
0
1
オフセット後の下付き
0
1
2
3
4
5
6
7
8
9
要素の下付き
50
51
52
53
54
55
56
57
58
59
加算されたカウント配列は
加算の原則は、各要素の出現回数=その前のすべての要素の出現回数+その要素の出現回数
加算回数
1
3
4
5
6
8
9
9
9
10
オフセット後の下付き
0
1
2
3
4
5
6
7
8
9
要素の下付き
50
51
52
53
54
55
56
57
58
59
加算されたカウント配列要素の値は、要素の位置に等しくなります.たとえば、下付き6の要素値は9で、元の数列を表す値56の最終的なソートは、9番目に最適化されたコードです.
def count_sort2(arr):
maxi = max(arr)
mini = min(arr)
count_arr_length = maxi - mini + 1 # , 4-9 9+1-4=6
count_arr = [0 for _ in range(count_arr_length)] # 0
for value in arr:
count_arr[value - mini] += 1 #
# count_arr[i] <=i ,
for i in range(1, count_arr_length):
count_arr[i] = count_arr[i] + count_arr[i - 1]
new_arr = [0 for _ in range(len(arr))] #
for i in range(len(arr)-1, -1, -1): #
new_arr[count_arr[arr[i] - mini] - 1] = arr[i] # -1 0
count_arr[arr[i] - mini] -= 1 # ,
return new_arr
if __name__ == '__main__':
user_input = input(' , \",\" :
').strip()
#strip() ( )
unsorted = [int(item) for item in user_input.split(',')]
print(count_sort2(unsorted))
ここで私が言った比較はあまり分かりにくいかもしれませんが、カウントソートの詳細については、ここをクリックして確認してください.
カウント・ソートは、最大値と最小値の差が大きくないリストに適用されます.リストの最小値が1で、最大値が1億であれば、カウント・ソートには1億+1の長さのリストを開く必要があります.時間がかかります.