クラスノート:挿入ソート

挿入ソートの挿入の主な動作
、その基本的な考え方です:レコードは、そのサイズのキーに従ってソートするたびに行に挿入されているがソートされたレコードまでのすべての行まで、順序付けられたシーケンスでソート。
挿入ソート方法は、以下の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)です。

公開された48件の元の記事 いいね25 2453にアクセス

おすすめ

転載: blog.csdn.net/qq_43628959/article/details/104433077