C++实现插入排序的总结

一.直接插入排序(Direct insertion sort)概述


在为排序序列中,构建一个子排序序列,直至全部数据排序完成

将代排序的数,插入到已经排序的序列中合适的位置

增加一个哨兵,放入比较值,让它和后面已经排好的序列比较,找到合适的插入点

 二.直接插入排序原理

初始值:[1 9 8 5 6]

第一趟:[0 1 9 8 5 6] [9 1 9 8 5 6]  -> [1 9 8 5 6]                   
#如大家所看到的,和初始值必须,我在第一个位置上增加了一个数字0,这个数字0的位置我们称其为哨兵,接下来我们直接取初始值的第二个索引9和它前面一个索引比较(第一个索引相比较),哨兵9比1大,则不需要交换位置,本轮比较结束。

第二趟:[8 1 9 8 5 6] [8 1 ? 9 5 6] [8 1 8 9 5 6] -> [1 8 9 5 6]           
#拿到上一轮比赛结果,接下来我们直接取初始值的第三个索引8和它前面一个索引比较,本轮哨兵为8,而哨兵8比9小,因此,我们需要把9往右移动一位,此时哨兵被插入8和9交换位置索引变为第二个索引,此时依旧需要和前面的一个索引进行比较,很显然第一个索引为1,而哨兵为8,哨兵8比1大,则不需要交换位置,本轮比赛结束。(简单的说就是如果比本轮哨兵大就相互交换位置,如果比本轮哨兵小则本轮结束)

第三趟:[5 1 8 9 5 6] [5 1 8 ? 9 6] [5 1 ? 8 9 6] [5 1 5 8 9 6] -> [1 5 8 9 6]   
#拿到上一轮比赛结果,接下来我们直接去初始值的第四个索引5和它前面一个索引比较,本轮哨兵为5,而哨兵5比9小,因此他们需要相互交换位置,接着哨兵5再和它前面一个索引比较,哨兵5比8小,继续交换位置,然后继续和它前面一个索引比价,发现哨兵5比1大,终止本轮比赛。

第四趟:[6 1 5 8 9 6] [6 1 5 8 ? 9] [6 1 5 ? 8 9] [6 1 5 6 8 9] -> [1 5 6 8 9]    
#拿到上一轮的结果,继续重复插入排序比较,经过上面3次比较,想必大家也清楚它是如何排序的了,最终经过四趟比较,得到的排序是:1 5  6 8 9

思路:后面去前面想比较,一次比较,一次换位置,比较一次,换一次位置。

插入排序与选择排序的比较与实现:

SortTestHelper.h:

#ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H
#define INC_04_INSERTION_SORT_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>

using namespace std;


namespace SortTestHelper {

    int *generateRandomArray(int n, int range_l, int range_r) {

        int *arr = new int[n];

        srand(time(NULL));
        for (int i = 0; i < n; i++)
            arr[i] = rand() % (range_r - range_l + 1) + range_l;
        return arr;
    }

    int *generateNearlyOrderedArray(int n, int swapTimes){

        int *arr = new int[n];
        for(int i = 0 ; i < n ; i ++ )
            arr[i] = i;

        srand(time(NULL));
        for( int i = 0 ; i < swapTimes ; i ++ ){
            int posx = rand()%n;
            int posy = rand()%n;
            swap( arr[posx] , arr[posy] );
        }

        return arr;
    }

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

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

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

        for (int i = 0; i < n; i++)
            cout << arr[i] << " ";
        cout << endl;

        return;
    }

    template<typename T>
    bool isSorted(T arr[], int n) {

        for (int i = 0; i < n - 1; i++)
            if (arr[i] > arr[i + 1])
                return false;

        return true;
    }

    template<typename T>
    void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {

        clock_t startTime = clock();
        sort(arr, n);
        clock_t endTime = clock();
        cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;

        assert(isSorted(arr, n));

        return;
    }

};
#endif //INC_04_INSERTION_SORT_SORTTESTHELPER_H

SelectionSort.h(选择排序):

#ifndef INC_04_INSERTION_SORT_SELECTIONSORT_H
#define INC_04_INSERTION_SORT_SELECTIONSORT_H
#include <iostream>
#include <algorithm>

using namespace std;


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

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

        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;

        swap( arr[i] , arr[minIndex] );
    }
}
#endif //INC_04_INSERTION_SORT_SELECTIONSORT_H

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;
}

结果的比较:

利用赋值语句改进插入排序算法(其他不变改进主函数的插入排序算法): 

改进后的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 ++ ) {
		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;	
				 
    }
}

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;
}

改进后的结果:

发布了195 篇原创文章 · 获赞 87 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_41479464/article/details/102755815