数据结构与算法C++之插入排序(续)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majinlei121/article/details/83789780

上一篇数据结构与算法C++之插入排序中使用C++实现了插入排序算法,但是使用了交换操作(swap),一次swap操作包括三次移位操作,造成运行时间比较长,本篇博客对其改进。
(1)首先,考虑第一个元素8,此时只有一个元素,是排好序的
在这里插入图片描述
(2)然后考虑第二个元素6
在这里插入图片描述
(3)将元素6拷贝一份,保存起来
在这里插入图片描述
(4)此时比较元素6与前面的元素8的大小关系
在这里插入图片描述
(5)如果后面的元素6比前面元素8小,那么将前面的元素8向后移动一个位置,元素6向前移动一个位置
在这里插入图片描述
(6)此时已经是第一个位置了,前面没有元素了,就将元素6赋值给该位置,此时前两个元素已经排好序了
在这里插入图片描述
(7)再考虑下一个元素2,同样将元素2拷贝一份,保存起来,比较元素2和前面的元素8的大小关系
在这里插入图片描述
(8)此时2比8小,所以将8后移一个位置,然后指针向前移动
在这里插入图片描述
(9)此时2比前一个元素6小,所以将元素6向后移动一个位置,元素2向前移动一个位置
在这里插入图片描述
(10)此时已经是第一个元素,元素2没有前面的元素可比较的了,因此将2赋值给第一个位置
在这里插入图片描述
(11)以此类推,不使用swap操作,实现插入排序

C++程序实现为:

#include <iostream>

#ifndef _SORTINGHELP_H_
#define _SORTINGHELP_H_

#include "SortingHelp.h"

#endif // _SORTINGHELP_H_

using namespace std;

template<typename T>
void InsertionSortingImproved(T arr[], int n){
    for (int i = 0; i < n - 1; i++){
        T temp = arr[i+1];
        int j;
        for (j = i + 1; j > 0; j--){
            if (arr[j-1] > temp){
                arr[j] = arr[j-1];
            }
            else{
                break;
            }
        }
        arr[j] = temp;
    }
    return;
}

//template<typename T>
//void InsertionSortingImproved(T arr[], int n){
//    for (int i = 1; i < n; i++){
//        T temp = arr[i];
//        int j;
//        for (j = i; j > 0 && arr[j-1] > temp; j--){
//            arr[j] = arr[j-1];
//        }
//        arr[j] = temp;
//    }
//}


//int main(){
//    int a[] = {10,9,8,6,6,5,5,3,2,2};
//    int n = 10;
//    InsertionSortingImproved(a, n);
//    for(int i = 0; i < n; i++){
//        cout<<a[i]<<" ";
//    }
//    cout<<endl;
//    return 0;
//}


int main()
{
    int n = 10000;
    int *arr = generateRandomArray(n, 0, n);
    int *arr2 = copyIntArray(arr, n);
    testSorting("SelectionSorting", SelectionSorting, arr, n);
    testSorting("InsertionSortingImproved", InsertionSortingImproved, arr2, n);
    delete[] arr;//最后删除数组开辟的空间
    delete[] arr2;
    return 0;
}

上面程序中引用的一些函数在下面的头文件SortingHelp.h中,输出结果为
在这里插入图片描述
可以看出改进后的插入排序算法运行时间比选择排序要短了,证明改进有效
插入排序算法中,一个元素一旦找到合适的位置,那么排序操作就终止了,那么对于一个已经很有序的数组来讲(无序的元素比较少),大部分元素已经在合适的位置,所以它们的插入操作会很快就终止,因此在这种情况下插入排序算法的效率是很高的
为了很好的说明这个问题,我们创建一个近乎有序的数组放在SortingHelp.h文件中,然后进行运行时间比较,SortingHelp.h如下:

//SortingHelp.h

#include <iostream>
#include <ctime>  //time()函数
#include <cstdlib> //rand()函数
#include <cassert> //assert()函数


using namespace std;

int* generateRandomArray(int n, int rangeL, int rangeR){//生成随机数组
    assert(rangeL < rangeR);
    int *arr = new int[n];
    srand(time(NULL));
    for (int i = 0; i < n; i++){
        arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
    }
    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;
}


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 testSorting(string sortName, void(*sorting)(T[], int), T arr[], int n){//第二个参数是传入排序函数的指针

    clock_t startClock = clock();
    sorting(arr, n);
    clock_t endClock = clock();
    assert(isSorted(arr, n));
    cout<<sortName<<" : "<<double(endClock-startClock)/CLOCKS_PER_SEC<<" s"<<endl;
    return;
}

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

template<typename T> //定义模板类型,使对各种数据类型都适用,如double,float,string
void SelectionSorting(T a[], int n){//选择排序算法
    for (int i = 0; i < n; i++){
        int minIndex = i;
        for (int j = i + 1; j < n; j++){
            if (a[j] < a[minIndex])
                minIndex = j;
        }
        swap(a[i], a[minIndex]);
    }
}

测试程序为

#include <iostream>

#ifndef _SORTINGHELP_H_
#define _SORTINGHELP_H_

#include "SortingHelp.h"

#endif // _SORTINGHELP_H_

using namespace std;

template<typename T>
void InsertionSortingImproved(T arr[], int n){
    for (int i = 0; i < n - 1; i++){
        T temp = arr[i+1];
        int j;
        for (j = i + 1; j > 0; j--){
            if (arr[j-1] > temp){
                arr[j] = arr[j-1];
            }
            else{
                break;
            }
        }
        arr[j] = temp;
    }
    return;
}
int main()
{
    int n = 10000;
    //int *arr = generateRandomArray(n, 0, n);
    int *arr = generateNearlyOrderedArray(n, 100);//生成只有200个无序元素的数组
    int *arr2 = copyIntArray(arr, n);
    testSorting("SelectionSorting", SelectionSorting, arr, n);
    testSorting("InsertionSortingImproved", InsertionSortingImproved, arr2, n);
    delete[] arr;//最后删除数组开辟的空间
    delete[] arr2;
    return 0;
}

输出结果为
在这里插入图片描述
可以看出排序一个近乎有序的数组,插入排序只用了0.002s,对于近乎有序的数组来讲,插入排序算法的运行效率是很高的。

猜你喜欢

转载自blog.csdn.net/majinlei121/article/details/83789780