基础排序算法

下面分别列举了选择排序、插入排序、冒泡排序和希尔排序三种排序方法。
在下面的插入排序中,我做了很大改进,放弃了采用交换的方式,因为swap的效率太低了,所以我们改用挨个移位,在移动不了的情况之下进行复制的方法。

// used for test
// Created by lizeyi on 2020/11/16.
//

#ifndef ALGROTHIM_SORTTESTHELPER_H
#define ALGROTHIM_SORTTESTHELPER_H

#include <cstdlib>
#include <vector>
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;


namespace SortTestHelper{

    //插入排序
    template<typename T>
    void insertSort(T arr[],int n){
//在这边 插入排序的第0个元素就不用考虑了,每一次把当前位置的元素和前一个元素作比较
        for (int i = 1;i<n;i++){
            T e = arr[i];
            int j;
            for ( j = i; j >0 && arr[j-1]>e  ; j--) {
                arr[j] = arr[j-1];
            }
            arr[j] = e;
        }

    }

    //选择排序
    template<typename T>
    void selectionSort(T arr[],int n){
        for (int i = 0; i < n; ++i) {
            //寻找【i , n】区间里的最小值
            int minIndex = i;
            for (int j = i+1; j < n; ++j) {
                if (arr[j]<arr[minIndex])
                    minIndex = j;
            }
            swap(arr[i],arr[minIndex]);
        }
    }

//    冒泡排序
    template<typename T>
    void bubbleSort( T arr[] , int n){

        bool swapped;
        //int newn; // 理论上,可以使用newn进行优化,但实际优化效果较差

        do{
            swapped = false;
            //newn = 0;
            for( int i = 1 ; i < n ; i ++ )
                if( arr[i-1] > arr[i] ){
                    swap( arr[i-1] , arr[i] );
                    swapped = true;

                    // 可以记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
                    // 实际优化效果较差,因为引入了newn这个新的变量
                    //newn = n;
                }

            //n = newn;

            // 优化,每一趟Bubble Sort都将最大的元素放在了最后的位置
            // 所以下一次排序,最后的元素可以不再考虑
            // 理论上,newn的优化是这个优化的复杂版本,应该更有效
            // 实测,使用这种简单优化,时间性能更好
            n --;

        }while(swapped);
    }

// 希尔排序(插入排序的改进版)
    template<typename T>
    void shellSort(T arr[], int n){

        int h = 1;
        while( h < n/3 )
            h = 3 * h + 1;
        // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...

        while( h >= 1 ){

            // h-sort the array
            for( int i = h ; i < n ; i ++ ){

                // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
                T e = arr[i];
                int j;
                for( j = i ; j >= h && e < arr[j-h] ; j -= h )
                    arr[j] = arr[j-h];
                arr[j] = e;
            }

            h /= 3;
        }
    }
    // 1    return new array.  number is n . range from rangeL to rangeR  [rangeL,rangR]
    template<typename T>
    int *generateRandomArray(int n , int rangeL , int rangeR){

        assert(rangeL<rangeR);

        T *arr = new T[n];

//            根据时间 设置随机种子
        srand(time(NULL));
        for (int i = 0;i<n;i++){
            arr[i]  = rand() % (rangeR-rangeL+1) + rangeL ;
        }
        return arr;
    }

//生成一个近乎有序的数组int类型  swapTimes交换的次数
    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;
    }



//  2   打印函数
    template<typename T>
    void printArray(T arr[],int n){

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

    //    4   判断是否是已排序的
    template <typename T>
    bool isSort(T arr[],int n){
        for (int i = 0;i<n-1;i++){
            if (arr[i] > arr[i+1]){
                return false;
            }
        }
        return true;
    }


    //3  计算排序时间
    template<typename T>
    void testSort(string sortName, void(* sort) (T [],int ),T arr[],int n){
            clock_t startTime  = clock();
            sort(arr,n);
            clock_t endTime = clock();

            assert(isSort(arr,n));
            cout<<sortName<<":"<<double(endTime-startTime) / CLOCKS_PER_SEC<<"s"<<endl;
        return;
        }

//        拷贝一个数组,不适用于拷贝一个对象 只能用于int string double
    template<typename T>
    T* copyIntArray(T a[],int n){
        static_assert(sizeof(int) == sizeof(T) || sizeof(string) == sizeof(T) || sizeof(double) == sizeof(T),
                      "T type is not the specified DataType including int and float");
        T* arr = new T[n];
//        拷贝原地址的头指针a,一个尾指针a+n ,目的地址的头指针
        copy(a,a+n,arr);
        return arr;
    }
}


#endif //ALGROTHIM_SORTTESTHELPER_H

参考文献

[1]维基百科.排序算法[EB/OL].https://zh.wikipedia.org/wiki/排序算法,2013-11-01.

posted @ 2020-11-17 17:17  不擅长纵横的捭阖家  阅读(102)  评论(0编辑  收藏  举报