知識リテラシー-アルゴリズム-ソートアルゴリズム

img

バブルソート

バブルソートの中心的なアイデアは次のとおりです:从无序队列的头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)元素放在队列的尾部,从而成为有序队列的一部分

バブルソートは2つのforループを維持し、最初のforループは回数を制御し、2番目のforループはペアワイズ比較を制御します。、注意する必要があります:バブルソートはどこから来るのですか?通常、それは右から出現します。つまり、右(キューの末尾)は順序付けられたキューです。

public void bullleSort(int[] nums){
    
    
    for(int i = 0;i < nums.length - 1;i++){
    
    
        for(int j = 1;j < nums.length  - i;j++){
    
    
            if(nums[j - 1] < nums[j]){
    
    
                int temp = nums[j - 1];
                nums[j - 1] = nums[j];
                nums[j] = temp;
            }
        }
    }
}

コードの説明:最初のforループは回数を制御し、iの初期値が0で、上限(取得)がnum.length-2であることは明らかです。考え:別の数値(1 )?単純な回数の制御であれば、最初から大きな問題ではありませんが、その後のforループでは、ソートされた要素の数という重要な役割も担っています。前述のように、順序付けられていないキューの先頭から始まり、末尾で終わりますが、末尾がどこにあるかをどのようにして知ることができますか?このi変数に依存する

2番目のforループは、ペアワイズ比較を制御します。iとi -1の比較に慣れているため、初期値は1で、上限(取得)はnun.length-i-1です。

最適化

シーケンス{2,1,3,4,5、}の場合、最初の比較が行われた時点でシーケンスはすでに順番になっていますが、その後の比較は続行されるため、最適化を実行できます。

public void bullleSort(int[] nums){
    
    
    boolean flag = true;
    for(int i = 0;i < nums.length - 1 && flag;i++){
    
    
        flag = false;
        for(int j = 1;j < nums.length  - i;j++){
    
    
            if(nums[j - 1] > nums[j]){
    
    
                int temp = nums[j - 1];
                nums[j - 1] = nums[j];
                nums[j] = temp;
                flag = true;
            }
        }
    }
}

パフォーマンス分析

時間計算量:最小時間は1回実行するのにO(n)であり、最悪の場合を比較する必要があり(n-1)、次に合計式に従ってO(n(n-1)/ 2)を取得するため、平均的な複雑さはO(N2)です

スペースの複雑さ:一時変数O(1)が必要です

安定性:>が使用されているため、安定したアルゴリズムです。

ソートを選択

基本的な考え方:每一趟从待排序序列中选择一个最大或者最小的元素放在没有排序的尾部

public void selectionSort(int[] nums){
    
    
    for(int i = 0;i < nums.length - 1;i++){
    
    
        int minIndex = i;
        for(int j = i;j < nums.length;j++){
    
    
            if(nums[j] < nums[minIndex]){
    
    
                minIndex = j;
            }
        }
        int temp = nums[minIndex];
        nums[minIndex] = nums[i];
        nums[i] = temp;
    }
}

パフォーマンス分析

時間計算量:O(N2)

スペースの複雑さ:O(1)

安定性:{_ 7,7,1,2}などの不安定。最初の選択肢が1であるため、{1,7_7,2}になるため、不安定になります。

挿入ソート

基本的な考え方:每趟将一个元素,插入到已经排好序的正确位置

public void insertionSort(int[] nums){
    
    
    for(int i = 1;i < nums.length;i++){
    
    
        int temp = nums[i];
        int j;
        for(j = i - 1;j >= 0 && temp < nums[j];j--){
    
    
            nums[j + 1] = nums[j];
        }
        nums[j + 1] = temp;	//注意这里是j+1 因为上面for循环最后还是进行了j--
    }
}

同じことが2つのforループです。1つ目は挿入数を制御し、2つ目は挿入する位置を制御し、いくつかの要素を元に戻し、現在の要素を正しい位置に挿入します。

パフォーマンス分析

時間計算量:O(N2)

スペースの複雑さ:O(1)

安定性:安定

ヒルソート

基本的な考え方:在插入排序的基础上进行分组排序,插入排序是将所有元素看做一个组,而希尔排序是没隔一个步长分为一个组,组内进行插入排序,有了插入排序的思想应该很好理解

puboic void shellSort(int[] nums){
    
    
    //控制分组
    for(int gap = nums.length/2; gap > 0;gap /= 2){
    
    
        //和插入排序一样只是上步长为1改为gap
        for(int i = gap;i < nums.length;i++){
    
    
            int temp = nums[i];
            int j;
            for(j = i - gap;i >= 0;temp < nums[j];j -= gap){
    
    
                nums[j + gap] = nums[j];
            }
            nums[j + gap] = nums[j];
        }
    }
}

パフォーマンス分析

時間計算量:ヒルソートの複雑さはギャップの選択によって異なりますが、O(N2)未満である必要があります

スペースの複雑さ:O(1)

安定性:安定

マージソート

マージソートは、典型的な分割統治法のアイデアです。要素はデフォルトで順序付けられているため、最初に配列を1つの要素のみで各グループに分割し、次にそれを閉じてコードを直接確認します。

public int[] sortArray(int[] nums) {
    
    
    int[] temp = new int[nums.length];
    mergeSort(nums, 0, nums.length - 1, temp);
    return nums;
}
public void mergeSort(int[] nums, int left, int right, int[] temp){
    
    
    if(left >= right)	return;
    int mid = (left + right) >> 1;
    mergeSort(nums, left, mid, temp);
    mergeSort(nums, mid + 1, right, temp);
    int k = left, p = mid + 1, t = 0;
    while(k <= mid || p <= right){
    
    
        if(p > right || (k <= mid && nums[k] < nums[p])){
    
    
            temp[t++] = nums[k++];
        }else{
    
    
            temp[t++] = nums[p++];
        }
    }
    for(int q = 0; q < t;q++){
    
    
        nums[left + q] = temp[q];
    }
}

パフォーマンス分析

時間計算量:O(nlogn)

スペースの複雑さ:O(n)

安定性:安定

ヒープソート

基本的な考え方:大きなトップパイルまたは小さなトップパイルを作成し、添え字が0の要素を使用して、大きなトップパイル(小さなトップパイル)の最後の要素と交換します。重要なポイントは次のとおりです。

  • 完全な二分木の最後の非リーフノード添え字:nums.length / 2-1
  • ルートノードの添え字がkの場合、ノードの左側のサブツリーノード:2k + 1、右側のサブツリー:2k + 2
public int[] sortArray(int[] nums) {
    
    
    heapSort(nums);
    return nums;
}
public void heapSort(int[] nums){
    
    
    for(int i = nums.length / 2 - 1;i >= 0;i--){
    
    
        adjustHeap(nums, i, nums.length);
    }
    for(int j = nums.length - 1;j > 0;j--){
    
    
        int temp = nums[j];
        nums[j] = nums[0];
        nums[0] = temp;
        adjustHeap(nums, 0, j);
    }
}
public void adjustHeap(int[] nums, int i, int length){
    
    
    int temp = nums[i];
    for(int k = 2 * i + 1; k < length;k = k * 2 + 1){
    
    
        if(k + 1 < length && nums[k] < nums[k + 1]){
    
    
            k++;
        }
        if(nums[k] > temp){
    
    
            nums[i] = nums[k];
            i = k;
        }else break;
    }
    nums[i] = temp;
}

クイックソート

クイックソートの基本的な考え方は、分割統治法を使用して配列内の各参照番号の正しい位置を見つけ、参照番号の左側の番号が番号よりも小さくなり、上の番号が右が数字よりも大きい場合は、数字の左右で再帰クイックソートを分割統治します。

public void quickSort(int[] nums, int left, int right){
    
    
    if(left >= right)	return;
    //基准数
    int temp = nums[left];
    int i = left;
    int j = right;
    while(i != j){
    
    
        while(i < j && nums[j] >= temp)	j--;
        while(i < j && nums[i] <= temp)	i++;
        if(i < j){
    
    
            int t = nums[i];
            nums[i] = nums[j];
            nums[j] = t;
        }
    }
    nums[left] = nums[i];
    nums[i] = temp;
    quickSort(nums, left, i - 1);
    quickSort(nums, i + 1, right);
}


おすすめ

転載: blog.csdn.net/weixin_44706647/article/details/115105501