挿入ソートの挿入の主な動作
、その基本的な考え方です:レコードは、そのサイズのキーに従ってソートするたびに行に挿入されているがソートされたレコードまでのすべての行まで、順序付けられたシーケンスでソート。
挿入ソート方法は、以下の2つのカテゴリがあります:1を、直接挿入ソート 2、シェルソート
直接挿入ソート
基本的な考え方:私の挿入時に(iは> 1)の記録は、I-1前の記録がソートされています。
解決すべき主要な問題
(1)最初の順序付けられたシーケンスを構築する方法?
(2)挿入するレコードの挿入位置を知るには?
直接挿入ソート処理の例
重要な質問(1)初期の順序付けられたシーケンスを構築する方法?
解決策:最初のレコードを最初の順序付きリストとして扱い、次に、2番目のレコードからn番目のレコードが挿入されるまで、それを順序付きリストに挿入します。
アルゴリズムの説明:
for (i=2; i<=n; i++)
{
插入第i个记录,即第i趟直接插入排序;
}
重要な質問(2)挿入するレコードの挿入位置を見つけるには?
解決策:i-1レコードの順序付き領域r [1]〜r [i-1]にレコードr [i]を挿入し、rを順に検索します。 [i]の正しい位置を挿入してから、対応する位置にr [i]を挿入します。
アルゴリズムの説明:
r[0]=r[i];
j=i-1;
while (r[0]<r[j])
{
r[j+1]=r[j];
j--;
}
r [0]には2つの機能があります:
1. r [i]の値はループに入る前に一時的に保存されるため、レコードの逆方向の移動によってr [i]の内容が失われることはありません;
2.挿入位置を見つけるループ内歩哨として行動する。
直接挿入ソートアルゴリズム
void insertSort (int r[ ], int n){
for (i=2; i<=n; i++) {
r[0]=r[i]; j=i-1;
while (r[0]<r[j]) {
r[j+1]=r[j];
j=j-1;
}
r[j+1]=r[0];
}
}
並べ替えの主な操作:移動、
直接挿入並べ替えアルゴリズムのパフォーマンス分析
最良の場合(正の順序):時間の複雑さはO(n)、
最悪の場合(逆順または逆順):時間の複雑さはO( n2)、
平均条件下(ランダム配置):時間の複雑さはO(n2)。
スペースパフォーマンス:レコード補助スペースが必要です。
直接挿入ソートアルゴリズムは、安定したソートアルゴリズムです。
直接挿入ソートアルゴリズムはシンプルで実装が簡単であり、ソートされるレコードが基本的に順序付けられている場合、またはソートされるレコードの数が少ない場合に適用できます。
ソートするレコードの数が多い場合、多数の比較および移動操作により、直接挿入ソートアルゴリズムの効率が低下します。
Hillソートの
改善の基礎:
(1)ソートされるレコードが基本的にキーコードで順序付けられている場合、直接挿入ソートの効率は大幅に改善されます;
(2)直接挿入ソートアルゴリズムは単純なので、ソートされるレコードの数nが小さい場合効率も非常に高いです。
基本的な考え方:ソートするレコード全体をいくつかのサブシーケンスに分割し、サブシーケンスに直接挿入してソートします。シーケンス全体のレコードが基本的に順序付けられている場合、すべてのレコードを直接挿入してソートします。
解決
すべき主要な問題(1)シーケンス全体が徐々に基本的な順序に発展するようにするには、ソートするレコードをどのように分割する必要がありますか?(2)サブシーケンス内で直接挿入ソートを実行するにはどうすればよいですか?
ソートするレコードを分割する目的は何ですか?
1. ソートするレコードの数を減らします;
2.シーケンス全体を基本的な順序に発展させます。
分割する方法?
サブシーケンスの構成は、単に「セグメントごとにセグメント化」することはできませんが、「増分」で区切られたレコードがサブシーケンスを形成します。
Hill挿入ソートプロセスの例
重要な質問(1)ソートするレコードを分割する方法は?
解決策:「増分」で区切られたレコードをサブシーケンスにグループ化します。
増分はどのように取る必要がありますか?
Hillによって提案された最も初期の方法は、d1 = n / 2、di + 1 = di / 2です。
アルゴリズムの説明:
for (d=n/2; d>=1; d=d/2)
{
以d为增量,进行组内直接插入排序;
}
重要な質問(2)サブシーケンス内で直接挿入ソートを実行する方法は?
解決策:レコードr [i]を挿入する場合、r [id](ジャンプ振幅はd)から前方にジャンプして挿入する位置を検索します。r[0]は一時的なストレージユニットであり、監視ユニットではありません。検索位置<0の場合、挿入位置が見つかったことを意味します。検索プロセス中、レコードシフトもd桁スキップされます。シーケンス全体で、最初のdレコードはdサブシーケンスの最初のレコードなので、挿入はd + 1番目のレコードから始まります。
アルゴリズムの説明:
for (i=d+1; i<=n; i++) //将r[i]插入到所属的子序列中
{
r[0]=r[i]; //暂存待插入记录
j=i-d;
while (j>0 && r[0]<r[j])
{
r[j+d]=r[j]; //记录后移d个位置
j=j-d; //比较同一子序列的前一个记录
}
r[j+d]=r[0];
}
ヒルソート
void Shellsort(int r[],int n){
for (d=n/2; d>=1; d=d/2){
for (i=d+1; i<=n; i++){
r[0]=r[i];
j=i-d;
while (j>0 && r[0]<r[j])
{
r[j+d]=r[j];
j=j-d;
}
r[j+d]=r[0];
}
}
}
アルゴリズムソート時パフォーマンスヒル
アルゴリズムのパフォーマンスをソートヒルは時間取ら増分の関数ではありませんが、今のところ誰もが最高の増分シーケンスの1を得ました。研究によると、ヒルソートの時間パフォーマンスはO(n2)とO(nlog2n)の間です。nが特定の範囲内にある場合、Hillソートに必要な比較の数と記録された動きの数は約O(n1.3)です。