(上)アルゴリズムを並べ替えたものプログラマが習得しなければなりません

今日のIT業界では、ミックス前ほど良好ではない、あまりにも多くの従業員が、間接的にしきい値を増やし、企業の採用につながったジュニアプログラマの黒字、その結果、より多くの知識を習得するために、プログラマが必要です。
アルゴリズムは長い間論争のトピックは、プログラマはアルゴリズム最後に把握する必要がありますか?一部の企業は直接インタビューの中でインタビュアーがアルゴリズムを手書きの質問をします、別の人は別の答えを持っているし、実際には、多くの企業は、アルゴリズムのための一定の要件を持っています。この技術は、今日の環境の顔は、私たちは将来の仕事に場所を占有するために、アルゴリズムを習得しなければならないので、プログラマは、偉大なテストを持っていたが必要です。
それでは、私は簡単にいくつかのソートアルゴリズムを説明し、私はあなたの助けを願っています。

1.バブルソート

バブルソート(バブルソート)、比較的単純なソートアルゴリズムです。
その順序は、(例えば降順として、AからZまでの最初の文字)は、交換エラーが引き継いだ場合は繰り返し、二つの隣接する要素を比較するために、ソートする列の要素を訪問しました。隣接する要素を交換する必要がないまで働い訪問要素が繰り返され、その要素の列が完成ソートされていると言うことです。
炭酸飲料中の二酸化炭素の気泡は、最終的にその名「バブル、同一の上部に浮いているかのよう名前は、大きな要素は徐々に列番号の上部(昇順または降順)に「フロート」を介して交換する実際のアルゴリズムから来ますソート。 "
デモ:
ここに画像を挿入説明
次のようにコードは次のとおりです。

@Test
public void bubbleSort() {
    int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
    // 统计比较次数
    int count = 0;
    // 第一轮比较
    for (int i = 0; i < arr.length - 1; i++) {
        // 第二轮比较
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换位置
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
            count++;
        }
    }
    System.out.println(Arrays.toString(arr));
    System.out.println("一共比较了:" + count + "次");
}

結果:

[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
一共比较了:105次

私たちは書くことができると考えているコードは、通常、バブルソートが書かれています。しかし、このプロセスは欠点があり、ソート処理が完了したときということですが、配列の要素をソートしますが、我々は上記の、ブール変数で、この代理を最適化できるように、この時間は、それはまだ、有用な作業を行わないこれ、比較することになります我々は105回の数を比較するようになったプログラム。
最適化されたコード:

@Test
public void bubbleSort() {
    int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
    // 统计比较次数
    int count = 0;
    for (int i = 0; i < arr.length - 1; i++) {
        boolean flag = true;
        for (int j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换位置
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = false;
            }
            count++;
        }
        if(flag) {
            break;
        }
    }
    System.out.println(Arrays.toString(arr));
    System.out.println("一共比较了:" + count + "次");
}

結果:

[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
一共比较了:95次

私たちは、最初の真であるブール変数にサイクルの開始を定義する交換素子場合、その後、値がfalseに設定されます。そこで、我々は、為替の要素があるかどうかを判断するために、このブール変数を渡すことができます。ブール引数がtrueの場合、それはあなたが発注を続けるそうでない場合は、外側のループの外にジャンプすることができますので、配列要素のこの時点ではそう長く説明はすでに、ソートされたどの要素交換が存在しないことを証明しています。結果は本当に多くのことを減少させる数を比較することによって理解することができます。

2. [ソート

選択ソート(選択ソート)簡単なソートアルゴリズムです。その動作原理は、第1のデータ要素は、(大)シーケンスの開始位置に格納された要素の選択された最小(または最大)から選別すること、および、最小の残存未分類の要素から検索します要素、その後、ソートされたシーケンスの終わりに。データのすべての要素数がソートされるようになるまでというように、ゼロです。一種である不安定なソート方法を選択します。
デモ:
ここに画像を挿入説明
次のようにコードは次のとおりです。

@Test
public void SelectionSort() {
    int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
    for (int i = 0; i < arr.length - 1; i++) {
        int index = i;
        for (int j = 1 + i; j < arr.length; j++) {
            if (arr[j] < arr[index]) {
                index = j;// 保存最小元素的下标
            }
        }
        // 此时已经找到最小元素的下标
        // 将最小元素与前面的元素交换
        int temp = arr[index];
        arr[index] = arr[i];
        arr[i] = temp;
    }
    System.out.println(Arrays.toString(arr));
}

結果:

[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

比較の各ラウンドの後に、最初のi個の要素が既にソートされているため実装がので、繰り返し比較を回避することであるインデックス変数iに格納された値の定義に非常に単純な、最初の外側ループでありますちょうど私ができる最初から、再び比較する必要はありません。その後、比較は、比較後の要素のインデックス位置が最小である場合は、それを交換することなく、あなたが移動することはできません要素のインデックス位置の比較に基づいて実行されています。要素は、要素のインデックス位置よりも小さい場合に検出されたインデックスに割り当てられた要素のインデックスは、次いで、比較は、比較が完了するまで続け、その後、比較の完了後に得られる配列インデックスの最小値は、この時点でそれであります単に要素要素を配置し、私は、インデックス位置を交換したいです。

3.挿入ソート

挿入ソート(挿入ソート)、簡単かつ安定ソートアルゴリズムです。あなたはすでに数の列に挿入された優れたデータのこの行に必要なデータの順序付けられたシーケンスを持っていますが、まだデータが発注したこの配列の挿入を必要とする場合は、この時間は、新しいソート方法を使用する必要がある-挿入ソート、挿入ソートの基本的な操作は、新しいを得るために、ソートされたデータにデータを持つことである、プラスアルゴリズムは、少量のデータに適しているソートシーケンスされたデータの数、時間の複雑さこれはO(N ^ 2)です。安定したソート方法。第2の部分はこれの唯一の要素を含むが最初の部分は、アレイのすべての要素を含むが、最後の要素を除く(スペースに挿入された位置を有するアレイを聞かせ):アレイが2つの部分に分かれてソートする挿入アルゴリズム(すなわち、挿入される要素)。第1選別部の完了後、最後の要素は、ソートされた第一の部分に挿入されています。
基本的な考え方は、その挿入ソートです:各ステップは、すべてが最後に挿入されるまで、キー値の大きさは、以前にアレイ上の所定の位置にソートに挿入されているによると、レコードの並べ替えになります。
デモ:
ここに画像を挿入説明
次のようにコードは次のとおりです。

@Test
public void InsertionSort() {
    int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
    for (int i = 1; i < arr.length; i++) {
        // 定义待插入的数
        int insertValue = arr[i];
        // 找到待插入数的前一个数的下标
        int insertIndex = i - 1;
        while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        arr[insertIndex + 1] = insertValue;
    }
    System.out.println(Arrays.toString(arr));
}

結果:

[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

そこでここでは、配列の要素は、我々はこれだけ、配列の最初の要素は順序付けられたシーケンスとして見られている、わからないので、我々は、配列の2番目の要素の開始から所定の位置に要素を見つけるために必要なものので、 。したがって、その後、[i]は、電流が第2の要素に保存され、その後、挿入される要素の最初の要素のインデックスを探しされ、すなわち、I-1、今回ARR一方を介して、外部ループから始まります比較するサイクル。
場合insertIndex 0未満、比較が完了しているためとき、ループを終了し、上記要素の全てします。挿入される要素が前の要素よりも小さい場合、比較プロセスでは、前部要素がシフトされ、前の要素の値、すなわち直接挿入される要素の位置に割り当てられます。初めに保存されたのでちょうど挿入する要素の値をすることができ、その前の要素に割り当てられているので、要素に挿入する必要があります。ループInsertIndexデクリメント操作が行われつつあるため、そのように前部要素インデックスべきinsertIndex + 1。要素が挿入される場合、それは循環に入らないしながら、割り当て後に変更、など後者の操作されないように、その位置の後にそのようなinsertIndex + 1位置は、まだ、前の要素よりも大きいです。

4.シェルソート

伝統的な挿入ソートアルゴリズムのような特定のシナリオではいくつかの問題が存在する[2,3,4,5,1]このような配列、我々は一種のあなたは数が1挿入したい見つけるために、彼らに時間を挿入すると、しかし、前にインサート1場合、5,4,3,2シフトした後、それぞれ、4つのステップを経るします。だから、結論する:小さい数が数値の場合、我々は比較的低くなり、その効率を挿入する必要があります。このシナリオの欠点は、ヒルが生まれソートを考えると、それはより効率的なバージョンの挿入ソートです。
概念の丘のようなものを見てみましょう:
ヒル(シェルのソート)をソート挿入ソートも「ズームインクリメントソート」(減少インクリメントソート)として知られ、それがランキングアルゴリズムより効率的な改良版に直接です。非定常ソートアルゴリズムをソートヒル。この方法は、名前の原因DLShellに1959年に提案しました。
シェルソート単位で記録パケットを押すの主題である、直接挿入ソートの使用は、各ソートアルゴリズムは、増加とともに徐々に減少し、より多くのキーワードをそれぞれ含む、増分に減少したときに、ファイル全体がひとつのセットに分割され、アルゴリズムは終了します。

デモ:
ここに画像を挿入説明
アニメーションあなたが理解していない場合、私はいくつかの静止画を貼り付けるためにここにいる:
ここに画像を挿入説明
コードの実装:

@Test
public void ShellSort() {
    int[] arr = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        // 对数组元素进行分组
        for (int i = gap; i < arr.length; i++) {
            // 遍历各组中的元素
            for (int j = i - gap; j >= 0; j -= gap) {
                // 交换元素
                if (arr[j] > arr[j + gap]) {
                    int temp = arr[j];
                    arr[j] = arr[j + gap];
                    arr[j + gap] = temp;
                }
            }
        }
    }

    System.out.println(Arrays.toString(arr));
}

結果:

[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

次いで、上記ブロックにおいて、アレイ15の長さは、第1ラウンドで、アレイは15/2 = 7群に分けられ、各グループ別の要素が横断します。実際に、それはグループ7の間隔で族元素の数がそのように分割された第1ラウンド内の要素間の間隔です。それは、各グループの要素を作製し、次いで、交換、その次とを行うことができます。

おすすめ

転載: www.cnblogs.com/blizzawang/p/11411533.html