插入排序法(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;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。