データ構造とアルゴリズム------挿入ソート

挿入ソート

挿入ソートは内部ソート方式に属します。ソートする要素については、要素を挿入して適切な位置を見つけ、ソートの目的を達成します。

ソート思考

ソートれるn個の要素は、順序付きリストと順序なしリストと見なされます。最初は、順序付きリストには1つの要素のみが含まれ順序なしリストにはn-1個の要素が含まれます。並べ替えプロセス中は毎回順序付けされていません。テーブルから最初の要素を取得し、その並べ替えコードを順序付きリスト要素の並べ替えコードと順番比較し、それを順序付きリストの適切な位置に挿入して、新しい順序付きリストにします。

ダイアグラム

ここに画像の説明を挿入

たとえば、上記のグラフデータが長すぎる場合、簡単な例を見てみましょう。配列の追加は[17,3,25,14,20,9]です。

挿入ソートでソートする方法は?

まず、最初の要素17は順序付きリストと見なされ残りは順序なしリストです。

最初の挿入:順序付きリストと比較して17より小さい挿入3。小さいものから大きいものへのルールに従って、17の前に挿入します。

[(3,17)25,14,20,9]になります

2番目の挿入:挿入25、順序付きリスト[3,17]と比較して、それは私たちのものより17大きく、17の後に配置されます

[(3,17,25)14,20,9]になります

3番目の挿入:挿入14、順序付きリスト(3,17,25)と比較すると、25未満で、前方を見て17未満で、次に前方を3より大きい3,17の間です。[(3,14,17,25)20,9]として挿入します

など、順序付けされていないリストにデータがなくなるまで続きます。

合計合計時間n-1が挿入されます

質問を聞いてください:

HKUSTには寮生がいます。成績は101、34、119、1です。

挿入ソートを使用して、スコアを小さいものから大きいものに並べ替えてください

コード

package com.wang.sort;

import java.util.Arrays;

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/24 16:05
 * @Description TODO
 * @pojectname 插入排序算法
 */
public class InsertSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    101,34,119,1};
        insertSort(arr);
    }
    //插入排序
    //逐步推到
    //第一次插入101,34,119,1====>34,101,119,1
    public static void insertSort(int[] arr){
    
    
        //定义待插入的数   34是下标为0的元素
        int insertValue = arr[1];
        int insertIndex = 1-1;//跟谁比较,跟前面的数比较
        //给insertValue找到插入位置
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //数组变成了 101,101,119,1
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第一次插入后的数组:"+ Arrays.toString(arr
        ));
        //第二轮
        insertValue = arr[2];
        insertIndex = 2-1;
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //数组变成了 34,101,119,1
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第二次插入后的数组:"+ Arrays.toString(arr));
        //第三轮
        insertValue = arr[3];
        insertIndex = 3-1;
        while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
            //insertIndex >=0保证我们找位置的时候不越界
            //insertValue <arr[insertIndex]==》说明我们还没找到位置
            //没有找到位置,说明我们的insertIndex代表的值大,往后面走
            arr[insertIndex+1] = arr[insertIndex];
            //我们的34被保存到了insertValue中
            insertIndex--;
        }
        //当退出while循环时,位置找到
        arr[insertIndex+1] = insertValue;
        System.out.println("第三次插入后的数组:"+ Arrays.toString(arr));
    }

}

終了時にinsertIndexを+1にする必要があるのはなぜですか?最初にinsertIndexを定義したときに1を引いたため、これは図と同様です。

図では、我々は要素を挿入するたびに、私たちはそこにあることがわかり、グリーンマーク当社insertIndexの位置である私が最初に誰比較する必要があり、ソート3、243のような、?今回は添え字3が2で4つの比較要素がインデックス1にある話したいのでinsertIndexは2-1で4つだけで、比較的少ないものが見つかりました。次に、whileループに入り、配列は244になり、InsertIndexは次のようになります。 0、次に判定サイクルに進みます。この時点で、insertValue> arr [insertIndex]、現在のinsertIndexは緑色の列2であり、3は緑色の数値よりも大きく、前の数値よりも小さいため、位置を挿入しましたinsertIndex + 1の位置に

挿入ソートアルゴリズム

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/24 16:05
 * @Description TODO
 * @pojectname 插入排序算法
 */
public class InsertSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    101,34,119,1};
        insertSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void insertSort(int[] arr){
    
    
        for (int i = 1; i <arr.length; i++) {
    
    
            //从1个元素开始,不需要减一,减一的话我们的最后一个元素就不插入了
            int insertValue = arr[i];
            int insertIndex = i-1;//跟谁比较,跟前面的数比较
            //给insertValue找到插入位置
            while (insertIndex >=0 && insertValue <arr[insertIndex]){
    
    
                //insertIndex >=0保证我们找位置的时候不越界
                //insertValue <arr[insertIndex]==》说明我们还没找到位置
                //没有找到位置,说明我们的insertIndex代表的值大,往后面走
                arr[insertIndex+1] = arr[insertIndex];
                //数组变成了 101,101,119,1
                //我们的34被保存到了insertValue中
                insertIndex--;
            }
            arr[insertIndex+1] = insertValue;
        }
    }
}

外側のforループは、その位置から挿入する準備をするように制御します。開始位置はarr [1]です。これは、arr [0]が順序付きリストと見なされるためです。

次に、外側のループはarr [1]、場所の検索arr [2]場所の検索......です。

内側のwhileループは、挿入したい位置であるかどうかを判断するために位置を見つけるために使用されます。これは、派生プロセスで述べたものです。
もちろん、arr [insertIndex + 1] = insertValueかどうかを尋ねる人もいます。;場所はまったく同じです、交換する必要はありませんか?判断する場合は追加できますが、この最適化はほとんど効果がありません

問題

単純な挿入ソートで発生する可能性のある問題を見てみましょう
。Arrayarr= {2,3,4,5,6,1}この時点で、挿入する必要のある数値1(最小)のプロセスは次のとおりです。
{2、3,4、5,6、6 }
{2,3,4,5,5、6}
{2,3,4,4,5、6}
{2,3,3,4,5、6}
{ 2,2、3,4,5、6}
{1,2,3,4,5、6}
結論挿入する数が少ない場合、バックシフトの数が大幅に増加し、影響があります。効率について。

では、挿入ソートを最適化する方法は?=====>ヒルソート

これが挿入ソート(直接挿入ソート)です。何が悪いのか、悪いのか、話しましょう。

おすすめ

転載: blog.csdn.net/qq_22155255/article/details/111639169