排序算法实现合集-经典排序算法实现与分析:冒泡排序,快速排序;直接插入排序,希尔排序;简单选择排序,堆排序;归并排序,基数排序;

针对排序算法,网上有比较好的讲解,参考自:程序员内功:八大排序算法和 程序员的内功——数据结构和算法系列 这里主要是学习过程中的重新记录,记录典型的排序算法实现模板;

排序算法稳定性讲解:

https://www.cnblogs.com/codingmylife/archive/2012/10/21/2732980.html  

https://blog.csdn.net/qq_43152052/article/details/100078825

排序的稳定性:首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。算法有的可以稳定,也可以不稳定(冒泡排序),稳定否要看算法是否符合稳定的定义;

冒泡排序:简单交换,从左端开始从大到小开始冒泡;每次冒泡后,最大值归位;减治思想,缩小问题规模;

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
vector<int> inarray;
int main(){
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    // 方法1
    while (cin >> tmp)
    {   
        inarray.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    for(i = 0; i < num; i++){
        cout << inarray[i] << " ";
    }
    cout << endl << endl;
    cout << "排序过程:" << endl;
    for(i=1; i < num; i++){
        for (int j = 0; j < num-i;j++){
            if(inarray[j] >= inarray[j+1]){
                int tmp = inarray[j];
                inarray[j] = inarray[j+1];
                inarray[j+1] = tmp;
            }
        }
        for(int k = 0; k < num; k++){
            cout << inarray[k] << " ";
        }
        cout << endl;
    }
    for(i = 0; i < num; i++){
        cout << inarray[i] << " ";
    }
    cout << endl;
    return 0;
}
冒泡排序实现模板
输入数据:
9 8 7 6 5 4 3 2 1 0 

排序过程:
8 7 6 5 4 3 2 1 0 9 
7 6 5 4 3 2 1 0 8 9 
6 5 4 3 2 1 0 7 8 9 
5 4 3 2 1 0 6 7 8 9 
4 3 2 1 0 5 6 7 8 9 
3 2 1 0 4 5 6 7 8 9 
2 1 0 3 4 5 6 7 8 9 
1 0 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9
冒泡排序输出样例

快速排序:通过一趟排序将排序的数据分割成独立的两部分,分割点左边都是比它小的数据,右边都是比它大的数; 使用分治方法,缩小问题规模,递归求解;

 

实现方法:

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr, int left, int right);

// 分解 第一版本;
int divide_1(vector<int> &arr, int left, int right){
    int base =  arr[left]; // 选取第一个元素为left;
    if(DEBUG){
        cout << endl << "base:" << base << " " << "left:" << left << " " << "right:" << right << endl;
    }
    while (true)
    {
        while (arr[right] >= base && right > left)
        {
            right --;
        }
        if (right == left){
            printarray(arr, left, right);
            break;
        }
        arr[left] = arr[right];
        arr[right] = base;
        left ++;
        printarray(arr, left, right);
        while (arr[left] <= base && left < right)
        {
            left ++;
        }
        if (left == right){
            printarray(arr, left, right);
            break;
        }
        arr[right] = arr[left];
        arr[left] = base;
        right --;
        printarray(arr, left, right);
    }
    return left; // 返回当前 base 所在的索引
}

// 分解第二版本
int divide_2(vector<int> &arr, int left, int right){
    int base = arr[left];
    while (left < right)
    {
        while (left < right && base <= arr[right])
        {
            right --;
        }
        arr[left] = arr[right];
        while (left < right && arr[left] <= base)
        {
            left ++;
        }
        arr[right] =  arr[left];
    }
    arr[left] = base;
    return left; // 返回当前base的索引;
}

// 快速排序算法
void quicksort(vector<int> &arr, int left, int right){
    // 设置递归出口
    if (left >= right){
        return;
    }
    int baseindex = divide_1(arr, left, right);
    quicksort(arr, left, baseindex-1);
    quicksort(arr, baseindex+1, right);
    // 快速排序算法,强调对问题原有数据的分解;
    // 每分解一次,一个元素归位;为减治;
    // 每分解一次,转化为两个独立的子问题;为分治;
}

// 打印函数;
void printarray(vector<int> &arr, int left, int right){
    if((left == -1 && right== -1)|| DEBUG){
        for(int i = 0; i < arr.size(); i++){
            cout << arr[i] << " ";
        }
        cout << endl;
    }
    if((left != -1&&right != -1)&& DEBUG){
        cout << "left:" << left << " " << "right:" << right << endl;
    }
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr, -1, -1);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 快速排序算法调用;其他代码为调试输出代码;
    quicksort(arr, 0, num-1); 

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr, -1, -1);
    return 0;
}
快速排序代码模板
bash-3.2$ c++ 快速排序.cc; ./a.out
输入数据:
7 8 9 6 5 4 3 2 1 

排序过程:

base:7 left:0 right:8
1 8 9 6 5 4 3 2 7 
left:1 right:8
1 7 9 6 5 4 3 2 8 
left:1 right:7
1 2 9 6 5 4 3 7 8 
left:2 right:7
1 2 7 6 5 4 3 9 8 
left:2 right:6
1 2 3 6 5 4 7 9 8 
left:3 right:6
1 2 3 6 5 4 7 9 8 
left:6 right:6

base:1 left:0 right:5
1 2 3 6 5 4 7 9 8 
left:0 right:0

base:2 left:1 right:5
1 2 3 6 5 4 7 9 8 
left:1 right:1

base:3 left:2 right:5
1 2 3 6 5 4 7 9 8 
left:2 right:2

base:6 left:3 right:5
1 2 3 4 5 6 7 9 8 
left:4 right:5
1 2 3 4 5 6 7 9 8 
left:5 right:5

base:4 left:3 right:4
1 2 3 4 5 6 7 9 8 
left:3 right:3

base:9 left:7 right:8
1 2 3 4 5 6 7 8 9 
left:8 right:8
1 2 3 4 5 6 7 8 9 
left:8 right:8

排序结果:
1 2 3 4 5 6 7 8 9 
快速排序输出样例
排序类型:交换排序;
排序方法:快速排序;
时间复杂度:
数据基本有序的时候,以第一个元素为基准,二分后;第一个子序列为空;此时效率较差;
当随机分布的时候,两个子序列的元素个数相接近的时候,此时效率最好;
最好时间复杂度:nlogn;
最坏时间复杂度:n2;
空间复杂度:因为每次排序,都需要1个空间,存储base;所以空间复杂度为 logn;最坏的时候为n;
算法稳定性:因为排序过程中,相等的元素可能会因为分区而交换顺序;所以不是稳定的算法;
快速排序为什么比冒泡排序快:因为快速排序利用分治的算法,把当前数据分为大于base的数组和小于base的数组;这样可以减少两个数组间的元素比较,而分治成两个独立的子问题;所以能够减少比较次数,从而加快了排序的速度;

直接插入排序:直接插入排序每一趟,将一个等待排序的记录,按照关键字的大小插入到前面有序队列中;直到扫描所有的数字后,每次都有一个数字归位排序完成;减治,缩小问题规模;

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

//直接插入排序
void insertsort(vector<int> &arr){
    int toins;
    for(int i =1;  i < arr.size(); i++){
        toins = arr[i];
        cout << "toins: " << toins << endl;
        int j;
        // 进行循环挪动左侧有序数组,找到待插入位置
        for (j = i-1; j >=0; j--)
        {
            if(arr[j]>= toins){
                arr[j+1] = arr[j];
            }else{
                break;
            }
        }
        arr[j+1] = toins; // 进行插入数组
        printarray(arr);
    }
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
    if(DEBUG){
        //cout << "left:" << left << " " << "right:" << right << endl;
    }
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 插入排序算法调用;其他代码为调试输出代码;
    insertsort(arr);

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
直接插入排序代码模板
bash-3.2$ c++ 直接插入排序.cc ; ./a.out
输入数据:
7 6 5 3 4 2 1 

排序过程:
toins: 6
6 7 5 3 4 2 1 
toins: 5
5 6 7 3 4 2 1 
toins: 3
3 5 6 7 4 2 1 
toins: 4
3 4 5 6 7 2 1 
toins: 2
2 3 4 5 6 7 1 
toins: 1
1 2 3 4 5 6 7 

排序结果:
1 2 3 4 5 6 7 
直接插入排序输出样例
排序类型:插入排序;
关键操作:元素比较次数;
时间复杂度:
最好时间复杂度:当数据在正序的时候,执行效率最好;时间复杂度为n;
最坏时间复杂度:当数据为逆序的时候,执行效率最差;时间复杂度为n2;
空间复杂度:不过使用交换还是插入,都需要使用一个空间存储要插入的值,复杂度为1;
算法稳定性:主要还是看实现方式,基本上是稳定的算法;当然也能实现为不稳定的;
优化方法:寻找插入位置的时候,可以使用二分查找来进行优化;

希尔排序:希尔排序是把记录按照一定增量(gap)分组,对每个组进行直接插入排序算法进行排序;当增量逐渐减小,每个组的关键词越来越多,当增量减少为1的时候,整个数据只要进行少量微调便可有序;希尔排序是直接插入排序的优化;总体目标是减少比较和交换次数;实现过程中,可以使用数组交换,也可以使用移动插入的方式来进行排序;

 

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

//希尔插入排序_移动插入方式实现;
void shellsort(vector<int> &arr){
    int size =  arr.size();
    for (int gap = size/2; gap >0; gap /=2)
    {
        cout << "gap: " << gap << endl;
        for (int i = 0; i < gap; i++) // 希尔排序的每次gap;
        {
            for (int j = i+gap; j < size; j += gap) // 类比于插入排序;使用j 抽象出一组序列;
            {
                int toins =  arr[j]; int k;
                cout << toins << endl;
                for (k = j-gap; k >= i; k -= gap)
                {
                    if (arr[k] >= toins)
                    {
                        arr[k+gap] = arr[k];
                    }else
                    {
                        break;
                    }
                }
                arr[k+gap] =  toins; // 使用移动插入的方式进行实现;
                printarray(arr);
            }
        }
    }
}

//希尔排序,使用交换方式实现; 类似于冒泡排序
void shellsort_2(vector<int> &arr){
    int size =  arr.size();
    for (int gap = size/2; gap >0; gap /=2)
    {
        cout << "gap: " << gap << endl;
        for (int i = 0; i < gap; i++) // 希尔排序的每次gap;
        {
            for (int j = i+gap; j < size; j += gap) // 类比于插入排序;使用j 抽象出一组序列;
            {
                int k;
                cout << "toins: " << arr[j] << endl;
                for (k = j-gap; k >= i; k -= gap)
                {
                    if (arr[k] >= arr[k+gap])
                    {
                        int tmp = arr[k+gap];
                        arr[k+gap] = arr[k];
                        arr[k] = tmp;
                    } else {
                        break;
                    }
                }
                printarray(arr);
            }
        }
    }
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
    if(DEBUG){
        //cout << "left:" << left << " " << "right:" << right << endl;
    }
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 希尔排序算法调用;其他代码为调试输出代码;
    shellsort(arr);

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
希尔排序模板
bash-3.2$ c++ 希尔排序.cc; ./a.out
输入数据:
7 6 5 3 4 2 1 

排序过程:
gap: 3
3
3 6 5 7 4 2 1 
1
1 6 5 3 4 2 7 
4
1 4 5 3 6 2 7 
2
1 4 2 3 6 5 7 
gap: 1
4
1 4 2 3 6 5 7 
2
1 2 4 3 6 5 7 
3
1 2 3 4 6 5 7 
6
1 2 3 4 6 5 7 
5
1 2 3 4 5 6 7 
7
1 2 3 4 5 6 7 

排序结果:
1 2 3 4 5 6 7 
希尔排序输出样例
排序种类:插入排序;
时间复杂度:
最坏时间复杂度:n2
平均时间复杂度:nlogn
空间复杂度为:1,每次插入排序的时候,需要一个辅助的空间;
稳定性:因为 gap 数据交换的时候,会交换相同元素的顺序,所以该算法不是稳定排序算法;
与直接插入排序对比:
直接插入排序也适用于链式存储结构,希尔排序对链式存储结构不友好;
希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显;

简单选择排序:每次从待排序队列中,找到最小的关键字记录,顺序放在已经排序记录的末尾,从左到右扫描;直到第一层循环扫描结束;思想比较简单;

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

//直接插入排序
void selectsort(vector<int> &arr){
    int size = arr.size();
    for (int i = 0; i < size-1; i++){ // 此处size-1是为了j = i+1到达末尾时,不会越界;
        int min = arr[i];
        int index = i;
        for (int j = i+1; j < size; j++){
            if(arr[j] < min){
                min = arr[j];
                index =  j;
            }
        }
        arr[index] = arr[i];
        arr[i] = min;
        printarray(arr);
    }
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
    if(DEBUG){
        //cout << "left:" << left << " " << "right:" << right << endl;
    }
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 插入排序算法调用;其他代码为调试输出代码;
    selectsort(arr);

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
简单选择排序模板
bash-3.2$ c++ 简单选择排序.cc; ./a.out
输入数据:
7 6 5 3 4 2 1 

排序过程:
1 6 5 3 4 2 7 
1 2 5 3 4 6 7 
1 2 3 5 4 6 7 
1 2 3 4 5 6 7 
1 2 3 4 5 6 7 
1 2 3 4 5 6 7 

排序结果:
1 2 3 4 5 6 7 
简单选择排序输出样例
排序类型:选择排序;
时间复杂度:n2; 选择排序比较次数和序列的初始排序无关;假设待排序的序列有N个元素,次数总为n(n-1)/2次;排序过程中随着序列情况不同,顺序情况也不同;
空间复杂度:简单选择排序,需要占用1个临时空间,用于保存最小值索引;交换时也需要一个临时空间;所以需要两个临时空间;
稳定性:稳定性与否与实现方式有关;可认为是不稳定的;

堆排序堆排序使用顺序存储的完全二叉树建造堆结构;分为小顶堆(每个节点的关键字都不大于其孩子节点的关键字)和大顶堆(每个节点的关键字都不小于其孩子节点的关键字);使用大顶堆来进行顺序排序;排序分为三个流程:建造堆(最后一个非叶子节点开始n/2),交换堆顶与最后一个元素并输出堆顶重新堆化(heapify);直到交换tree[0]和tree[1]为止;针对于数组中的每个节点tree[i]来说,其父节点为tree[(i-1)/2], 其左孩子节点为tree[2i+1],其右孩子节点为tree[2i+2]; 

堆(heap): 堆是计算机科学中一类特殊的数据结构的统称;堆可通常是一个可以看做一颗完全二叉树的数组对象;

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

// 交换数组中 i j 两个数字的位置;
void swapij(vector<int> &arr, int i, int j){
    int tmp =  arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

void heapify(vector<int> &arr, int n, int index){
    int max = index;
    int c1 = 2*index+1;
    int c2 = 2*index+2;
    if(c1 < n && arr[c1] > arr[max]){ // c1 >= arr.size(),该节点没有左孩子;
        max = c1;
    }
    if(c2 < n && arr[c2] > arr[max]){ // c2 >= arr.size(),该节点没有右孩子;
        max = c2;
    }
    if(max != index){ // 递归出口,改节点最大值不是index本身;
        swapij(arr, index, max);
        heapify(arr, n, max);
    }
}

void build_heap(vector<int> &arr){
    // 从最后一个非叶子节点开始;
    int n = arr.size();
    for(int i = n/2; i>=0; i--){
        heapify(arr, n, i);
        if (DEBUG){
            printarray(arr);
        }
    }
}

// 使用堆排序进行堆化;
void heapsort(vector<int> &arr){
    if(DEBUG){
        cout << "创建堆:" << endl;
    }
    build_heap(arr); // 第一步创建堆
    // 交换输出堆顶,重新堆化
    if(DEBUG){
        cout << "交换输出堆顶,重新堆化:" << endl;
    }
    int n = arr.size();
    for(int i = n-1; i>0; i--){
        swapij(arr, 0, i); // 交换堆尾和堆顶元素;
        heapify(arr, i, 0); // 重新对堆顶进行堆化;
        if (DEBUG){
            printarray(arr);
        }
    }
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 堆排序;
    heapsort(arr);

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
堆排序模板
bash-3.2$ c++ 堆排序.cc; ./a.out
输入数据:
1 5 4 3 10 

排序过程:
创建堆:
1 5 4 3 10 
1 10 4 3 5 
10 5 4 3 1 
交换输出堆顶,重新堆化:
5 3 4 1 10 
4 3 1 5 10 
3 1 4 5 10 
1 3 4 5 10 

排序结果:
1 3 4 5 10 
堆排序输出样例
排序类别:选择排序
时间复杂度:建立堆的时间为O(n)时间;每次调整堆的时间为logn的时间,总共调整n次;所以,时间复杂度为O(nlogn); log认为是以2为底;
空间复杂度:在交换过程中,需要1个辅助数组;为O(1)
算法稳定性:堆排序算法是不稳定的算法,因为在堆调整过程中,关键字比较和交换时节点到叶子节点的一条路径;因此就可能排在后面的节点交换到前面来;例如 12123,进行排序;你自己可以在图纸上演绎一下。

归并排序:归并排序 采用分治的思想,将排序问题,分为一些小的问题;然后进行递归求解;最后进行合并;求得最后的解;

分阶段就是把数组细分,治阶段就是把两个有序的数组合并成一个有序的数组;

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

void printij(vector<int> &arr, int i, int j){
    for (;i <= j; i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

void merge(vector<int> &arr, int start, int mid, int end){
    if(DEBUG){
        cout << "合并前:" << endl;
        printij(arr, start, mid);
        printij(arr, mid+1, end);
    }
    // 归并阶段
    vector<int> tmp; // 创建一个数据,用于保存归并排序的中间变量;
    int i = start;
    int s = start;
    int j = mid+1;
    while (i<= mid && j <=end)
    {
        if(arr[i]>=arr[j]){
            tmp.push_back(arr[j]);
            j++;
        }else{
            tmp.push_back(arr[i]);
            i++;
        }
    }
    if (i>mid){
        while (j<=end)
        {
            tmp.push_back(arr[j]);
            j++;
        }
    }
    if (j > end){
        while (i<=mid)
        {
            tmp.push_back(arr[i]);
            i++;
        }
    }
    for (int k = 0; k < tmp.size(); k++)
    {
        arr[start] = tmp[k]; // 注意此处的数组起点为 start;
        start++;
    }
    if (DEBUG)
    {
        cout << "合并后:" << endl;
        printij(arr, s, end);
        cout << endl;
    }
}

void mergesort(vector<int> &arr, int start, int end){
    if (DEBUG)
    {
        cout << "分解阶段: " << start << " " << end << endl;
    }
    if (start == end) return; // 递归出口
    int mid =  (end+start)/2;
    mergesort(arr, start, mid);
    mergesort(arr, mid+1, end);
    // 不同于快速排序,归并排序更强调于merge
    // merge 
    if (DEBUG)
    {
        cout << "合并阶段: " << start << " " << mid << " " << end << endl;
    }
    merge(arr, start, mid, end);
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 归并排序
    mergesort(arr, 0, arr.size()-1);

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
归并排序代码模板
bash-3.2$ c++ 归并排序.cc; ./a.out
输入数据:
1 5 10 3 4 

排序过程:
分解阶段: 0 4
分解阶段: 0 2
分解阶段: 0 1
分解阶段: 0 0
分解阶段: 1 1
合并阶段: 0 0 1
合并前:
1 
5 
合并后:
1 5 

分解阶段: 2 2
合并阶段: 0 1 2
合并前:
1 5 
10 
合并后:
1 5 10 

分解阶段: 3 4
分解阶段: 3 3
分解阶段: 4 4
合并阶段: 3 3 4
合并前:
3 
4 
合并后:
3 4 

合并阶段: 0 2 4
合并前:
1 5 10 
3 4 
合并后:
1 3 4 5 10 


排序结果:
1 3 4 5 10 
归并排序输出样例
排序种类:归并排序;
时间复杂度:归并排序就是一个二叉树;遍历的深度为logn;每层的合并数为n;总体时间为nlogn;
空间复杂度:合并过程中需要,大小为n的临时空间存储中间变量;复杂度为n;
算法稳定性:合并过程中相等元素的顺序不会改变;为稳定算法;
与其他算法比较:空间复杂度角度,首先选择堆排序,其次快速排序,最后是归并排序;时间复稳定角度来看,应该选择归并排序,因为堆排序和快速排序是不稳定的排序;
平均排序速度情况下考虑:应该选择快速排序;

基数排序:基数排序,也称为桶排序和箱排序,比较适合有限范围的关键字进行排序;由整数举例,其原理是将整数按位数切割成不同的数字,然后按每位分别进行比较;先由个位开始然后分配到10个桶中,然后依次收集;再按照十位进行排序,然后百位,直至最高位;

#define DEBUG 1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void printarray(vector<int> &arr);

// 针对于整数的桶排序
void bucketsort(vector<int> &arr, int base){
    int n = arr.size(); // 确定待排序数字的总数;
    //建立10个桶
    vector<int> bucket[10];
    for(int i = 0; i < n; i++){
        bucket[(arr[i]/base)%10].push_back(arr[i]);
    }
    if(bucket[0].size()==n){
        return; //递归出口
    }
    int index = 0;
    for(int i = 0; i < 10; i++){
        for (int j = 0; j < bucket[i].size(); j++)
        {
            arr[index] = bucket[i][j];
            index++;
        }
    }
    if(DEBUG){
        printarray(arr);
    }
    bucketsort(arr, base*10);
}

// 打印函数;
void printarray(vector<int> &arr){
    for(int i = 0; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main(){
    vector<int> arr; 
    freopen("in.txt", "r", stdin); // 重定向到输入 
    int i = 0; 
    int tmp; 
    while (cin >> tmp)
    {   
        arr.push_back(tmp);
        // cout << inarray[i] << endl;
        i++;
    }
    int num =  i;
    cout << "输入数据:" << endl;
    printarray(arr);
    cout << endl;
    if (DEBUG){
        cout << "排序过程:" << endl;
    }

    // 基数排序
    bucketsort(arr, 1); // 桶排序算法;

    if (DEBUG){
        cout << endl;
    }
    cout << "排序结果:" << endl;
    printarray(arr);
    return 0;
}
基数排序代码实现
bash-3.2$ c++ 基数排序.cc; ./a.out
输入数据:
614 738 921 485 637 101 215 530 790 306 

排序过程:
530 790 921 101 614 485 215 306 637 738 
101 306 614 215 921 530 637 738 485 790 
101 215 306 485 530 614 637 738 790 921 

排序结果:
101 215 306 485 530 614 637 738 790 921 
基数排序输出样例
排序类别:基数排序;
时间复杂度:O(k*(n+m)); k为关键字种类;n为关键字的个数;m为每种关键字(桶的个数)的取值范围;
空间复杂度:O(n) 需要m个桶的空间来存储值;但是桶的总容量为n;如果使用链表来实现的话,桶空间可以进行复用;
算法稳定性:每次都是从左到右,按照关键词,装入对应桶中,在装入的过程中没有交换元素位置,所以基数排序算法是稳定的;

保持更新,转载请注明出处;更多内容请关注cnblogs.com/xuyaowen;如果对您有帮助,欢迎点击推荐~!

本文章所有排序代码实现位于:https://github.com/yaowenxu/codes/tree/master/排序算法 

注:本题图整理自参考博客;

原文地址:https://www.cnblogs.com/xuyaowen/p/sort-algos.html