算法之插入排序法

插入排序法(Insertion Sort)

一,概念

  • 自行總結:當前元素小於(大於)前一個元素,則當前元素就插入到前一個元素之前,直到排序完成

  • 區別:

    • 插入排序:二層循環可以提前結束循環
    • 選擇排序:二層循環要全部執行
  • 時間複雜度:O(n2)

  • 特點:如果待排序數組近乎有序,那可以很快結束二層循環,時間複雜度趨於O(n)

二,圖示

更接近,插入排序改進方法的邏輯
在這裏插入圖片描述

三,C++實現

main.cpp

#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "SelectionSort.h"

using namespace std;

template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        // 尋找元素arr[i]合適的插入位置(和之前元素進行比較)
        // 插入排序的二層循環可以提前結束,但選擇排序的二層循環要完整執行找到最小值
        // 寫法1
        for( int j = i ; j > 0 ; j-- )
            if( arr[j] < arr[j-1] )
                swap( arr[j] , arr[j-1] );
            else
                break;

        // 寫法2
//        for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
//            swap( arr[j] , arr[j-1] );

    }

    return;
}

int main() {

    int n = 10000;
    cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
    int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int *arr2 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
    SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);

    delete[] arr1;
    delete[] arr2;

    cout<<endl;

    return 0;
}

SortTestHelper.h

 int *copyIntArray(int a[], int n){

        int *arr = new int[n];
        copy(a, a+n, arr);
        return arr;
    }

四,js實現

// 插入排序
function insertionSort(arr, n){
	for(let i = 1; i < n; i++){
	    // 尋找元素arr[i]合適的插入位置(和之前元素進行比較)
        // 插入排序的二層循環可以提前結束,但選擇排序的二層循環要完整執行找到最小值
	    for(let j = i; j > 0; j--){
	        if(arr[j]< arr[j-1]){
	        	[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
	        }else{
	        	break;
	        }
	    }
	}
	return arr;
}

// 生成隨機數組
function getRandom(n){
    let arr = [];
    for (let i = 0; i < n; i++){
    	arr[i] = Math.floor(Math.random() * n);
    }
    return arr;
}

insertionSort(getRandom(100),100);

五,排序時間比較

選擇排序比插入排序時間。插入排序雖然能提前結束循環,但是一直交換賦值。而選擇排序每次只有一次交換。

c++

int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);

SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);

js

let arr1 = getRandom(100);
// copy數組
let arr2 = [...arr1];

console.time("sort");
selectionSort(arr1,100);
console.timeEnd("sort");

console.time("sort");
insertionSort(arr2,100);
console.timeEnd("sort");

六,插入排序改進

問題:對於插入排序多次交換賦值的缺點,能不能改成一次賦值?

自行總結:把待插入的元素拿出,向前比較,比它大的元素後移,直到找到自己的位置,一次插入。

c++

void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {
        
        // 寫法3
        T e = arr[i];
        int j; // j保存元素e應該插入的位置
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}

js

// 插入排序
function insertionSort(arr, n){
	for(let i = 1; i < n; i++){
	    let e = arr[i];// 把待插入的元素拿出
	    let j = 0; // j保存元素e應該插入的位置
	    for(j = i; j > 0; j--){
	        if(e < arr[j-1]){ // 元素e向前比較
	        	arr[j] = arr[j-1];// 大於e的元素後移
	        }else{
	        	break;
	        }
	    }
	    // 當循環終止時(e > arr[j-1]),e找到自己位置爲j
	    arr[j] = e;
	}
	return arr;
}
發佈了134 篇原創文章 · 獲贊 165 · 訪問量 139萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章