挿入ソート、バイナリ検索の最適化
テン古典的なソートアルゴリズム!
序文
してください必ずこれを見て:準備のアルゴリズム事前知識+コード環境をソートします。
上記の内容は準備ができたら、それは一種の挿入を開始します!
挿入ソート
トランプを挿入ソートに非常に似てソート、カードの裏面には絵の前に挿入され、そのフロントカード秩序あることが徐々に増加し、完全に注文したまで。
実装プロセス
- ①実行時には、二つの部分に挿入されたシーケンスをソートします
ヘッドの既にされているソート、尾があるソートするには - ②各走査素子を傷つける
ヘッドデータが整然と残るようにその都度走査要素、それはヘッドの適切な位置に挿入されます
挿入ソート達成します
/**
* 插入排序
*/
public class InsertionSort1 <T extends Comparable<T>> extends Sort<T>{
@Override
protected void sort() {
for(int begin = 1; begin < array.length; begin++){
int cur = begin;
while(cur > 0 && cmp(cur, cur-1) < 0){
swap(cur, cur - 1);
cur--;
}
}
}
}
20000の値は[1、10000]乱数でソートされ生成されます。
挿入ソート - 逆にします
逆の順番とは何ですか?
- アレイ<2、3、8、6、1>は逆の順序である
:<2,1> <3,1> <8,1> <8,6> <6,1>、5つの逆順の合計
の時間複雑さの逆の挿入ソートの数に比例
- 逆より多くの、挿入ソートの高い時間複雑
明らかに、図中上から下へは、挿入ソート、徐々に効率を高めます。
挿入ソート - 最適化
アイデアは、[為替] [へ]移動することです
実装プロセス:
- 挿入される最初のバックアップ要素①
- ②順序付けられたデータ要素よりも大きな頭部が挿入さ、方向後方位置に向かって移動しています
- ③要素は、最終的な場所に挿入されます
/**
* 插入排序-优化
* 交换 -> 挪动
*/
public class InsertionSort2 <T extends Comparable<T>> extends Sort<T>{
@Override
protected void sort() {
for(int begin = 1; begin < array.length; begin++){
int cur = begin;
T v = array[begin]; // 将待插入元素备份
while(cur > 0 && cmp(v, array[cur-1]) < 0){
// 头部有序数据中比待插入元素大的,都朝尾部方向挪动1个位置
array[cur] = array[cur - 1];
cur--;
}
array[cur] = v; // 将待插入元素放到最终的合适位置
}
}
}
見つけることができる:20000の値は[1、10000]ランダムな番号でソートされた生成交換の数が0になります
複雑性と安定性
- 最悪、平均時間計算:O(N- 2)
- 最高の時間の複雑さ:O(n)は、
- 宇宙複雑:O(1)
- 属する安定したソート
- ときに非常に少ない、効率の挿入ソートが特に高いの逆
であっても速度O(nlog比N速いクイックソート)レベル
データ量が特に大きくはない、効率の挿入ソートも非常に良いです。
バイナリ検索
配列内の要素の位置を確認する方法?(アレイ内のすべての仮定は整数です)
- O(N):アレイは0トラバーサル検索開始位置、平均時間の複雑さから、乱れている場合
- (ログインO:配列を注文した場合、バイナリ検索は、最悪時間計算量を使用することができますN-)
バイナリ検索 - アイデア
- Vは、検索の要素が[END)レンジ、中間==(+端を開始)/ 2、始めることが想定されます
- V <mは、[バイナリ探索の範囲で、中間)を開始する場合
- V> mの場合に、[中間+ 1、端部)に二分探索の範囲内
- V ==メートルの場合、直接のリターン中旬
バイナリ検索 - 達成
/**
* 二分搜索
*/
public static int search(int[] array, int v){
if(array == null || array.length < 1) return -1;
int begin = 0;
int end = array.length;
while(begin < end){
int mid = (begin + end) >> 1;
if(v < array[mid]){
end = mid;
}else if(v > array[mid]){
begin = mid + 1;
}else{
return mid;
}
}
return -1;
}
複数の重複する値が存在する場合、リターンはありますか?
- 不確実
挿入ソート - バイナリサーチの最適化
挿入要素中Vは、することが可能であるバイナリ適切な挿入位置を検索し、そしてその要素vを挿入します
:以下の配列と仮定
項バイナリ検索返さ挿入位置:Vよりポジション以上の最初の要素を
- vが5、返品の場合は2
- vが1である場合は、0が返されます
- vが15、7リターンである場合
- vが8であれば、返す5
挿入ソート - バイナリ検索の最適化 - アイデア
- Vは、検索の要素が[END)レンジ、中間==(+端を開始)/ 2、始めることが想定されます
- V <mは、[バイナリ探索の範囲で、中間)を開始する場合
- V≥Mの場合、バイナリサーチの範囲の[中間+ 1、端部)まで
挿入ソート - セカンド検索の最適化 - 例
挿入ソート - バイナリ検索の最適化 - 実現
/**
* 插入排序-优化2
* 二分搜索进行优化
*/
public class InsertionSort3 <T extends Comparable<T>> extends Sort<T>{
@Override
protected void sort() {
for(int begin = 1; begin < array.length; begin++){
// 将遍历到的元素插入到前面已经排好序的序列中
insert(begin, search(begin)); //search() 查找到要插入的位置
}
}
/**
* 将source位置的元素插入到dest位置
*/
private void insert(int source, int dest){
T v = array[source]; // 备份要插入的元素
// 将 [insertIndex, begin)范围内的元素往右边挪动一个单位
for(int i = source; i > dest; i--){
array[i] = array[i - 1];
}
array[dest] = v;
}
/**
* 利用二分搜索找到index位置元素的待插入位置
* 已经排好序数组的区间范围是[0,index)
*/
private int search(int index){
int begin = 0;
int end = index;
while(begin < end){
int mid = (begin + end) >> 1;
if(cmp(array[index], array[mid]) < 0){
end = mid;
}else{
begin = mid + 1;
}
}
return begin;
}
}
20000の値は[1、10000]乱数でソートされ生成されます。
複雑性と安定性
唯一比較の数を減少させる、二分探索を使用して、しかし後の挿入ソート平均時間計算量は依然としてO(N 2)
- 最悪、平均時間計算:O(N- 2)
- 最高の時間の複雑さ:O(n)は、
- 宇宙複雑:O(1)
- 属する安定したソート