选择排序算法

众所周知,最优的排序算法的复杂度是O(nlogn),但在学习最优算法前,我们先来看看O(n^2)复杂度的算法,由简入难。

算法描述:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序的代码:

void selectionSort(int 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]);
    }
}

选择排序的改进

为了让selectionSort()能接受不同类型(float,string ,char,或自定义类型)的数组,使用模板函数对其进行改进:

template
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]);
    }
}

随机生成数组

当采用的数组个数较大时,不可能一个一个的列举出来,这里编写一个随机生成数组的程序,用来辅助数组的排序。此处建立一个命名空间SortTestHelper,用来放与排序测试相关的各种函数,包括生产随机数组generateRandomArray()、printArray()、testSort()、isSorted()等。
generateRandomArray()的实现

 //生成有n个元素的随机数组,每个元素的随机范围为[rangeL,rangeR]
    int *generateRandomArray(int n, int rangeL, int rangeR)
    {
        assert(rangeL <= rangeR);//#include
        int *arr = new int[n];
        srand(time(NULL));//#include
        for (int i = 0; i < n; i++)
        {
            arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
        }
        return arr;
    }

测试代码如下:

#include
#include"SortTestHelper.h"
using namespace std;
template
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]);
    }
}
int main()
{
    int n = 1000;
    int *arr = SortTestHelper::generateRandomArray(n, 0, n);
    selectionSort(arr, n);
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << ",";
    }
    cout << endl;
    delete[] arr;//注意要释放掉内存空间,否则发生内存泄漏
    system("pause");
    return 0;
}

上述打印过程也可放在SortTestHelper()命名空间中:
printArray()

    void printArray(T arr[], int n)
    {
        for (int i = 0; i < n; i++)
        {
            cout << arr[i] << " ";
        }
        cout << endl;
    }

则测试代码重新写如下:

    int n = 1000;
    int *arr = SortTestHelper::generateRandomArray(n, 0, n);
    selectionSort(arr, n);
    SortTestHelper::printArray(arr, n);
    delete[] arr;

如何衡量一个排序算法的性能?

算法在某个数据集上的执行时间可以衡量该算法的性能。接下来在SortTestHelper()空间中写一个衡量算法性能的函数testSort()
testSort()

//测试算法性能,传入的参数包括算法名称、算法函数本身,测试用例及用例长度
    template
    void testSort(string sortName, void(*sort)(T[], int),T arr[],int n)
    {
        //clock_t表示时钟周期的数据
        clock_t startTime = clock();
        sort(arr, n);
        clock_t endTime = clock();
        assert(isSorted(arr, n));
        //两次时钟周期差表示算法真正执行的时钟周期,CLOCKS_PER_SEC每秒时钟周期个数
        cout << sortName << double(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
        return;
    }

如何衡量排序算法的正确性?

代码如下:
isSorted()

//测试排序算法执行的正确性
    template
    bool isSorted(T arr[], int n)
    {
        for (int i = 0; i < n; i++)
        {
            if (arr[i] > arr[i + 1])
            {
                return false;
            }
            return true;
        }
    }

测试排序算法的性能

#include
#include"SortTestHelper.h"
using namespace std;
template
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]);
    }
}
int main()
{
    int n = 10000;
    int *arr = SortTestHelper::generateRandomArray(n, 0, n);
    SortTestHelper::testSort("selectionSort:", selectionSort, arr, n);
    delete[] arr;
    system("pause");
    return 0;
}

整个SortTestHelper()空间的代码如下:

#ifndef SELECTIONSORT_SORTTESTHELPER_H
#define SELECTIONSORT_SORTTESTHELPER_H
#include
#include
#include
#include
using namespace std;
namespace SortTestHelper
{
    //生成有n个元素的随机数组,每个元素的随机范围为[rangeL,rangeR]
    int *generateRandomArray(int n, int rangeL, int rangeR)
    {
        assert(rangeL <= rangeR);//#include
        int *arr = new int[n];
        srand(time(NULL));//#include
        for (int i = 0; i < n; i++)
        {
            arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
        }
        return arr;
    }
    template
    void printArray(T arr[], int n)
    {
        for (int i = 0; i < n; i++)
        {
            cout << arr[i] << " ,";
        }
        cout << endl;
        return;
    }
    //测试算法执行的正确性
    template
    bool isSorted(T arr[], int n)
    {
        for (int i = 0; i < n; i++)
        {
            if (arr[i] > arr[i + 1])
            {
                return false;
            }
            return true;
        }
    }
    //测试算法性能,传入的参数包括算法名称、算法函数本身,测试用例及用例长度
    template
    void testSort(string sortName, void(*sort)(T[], int),T arr[],int n)
    {
        //clock_t表示时钟周期的数据
        clock_t startTime = clock();
        sort(arr, n);
        clock_t endTime = clock();
        assert(isSorted(arr, n));
        //两次时钟周期差表示算法真正执行的时钟周期,CLOCKS_PER_SEC每秒时钟周期个数
        cout << sortName << double(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
        return;
    }
}
#endif  

说明:本文是在听了波波老师的数据结构算法课程后所做的笔记!

你可能感兴趣的:(选择排序算法)