经典排序算法练习

直接插入排序

#include <iostream>

// 打印列表
template<typename T>
void print(T arr[], int len){
    using namespace std;
    for(int i = 0; i < len; cout << arr[i] << " ", i++);
    cout << endl;
}

// 直接插入排序
template<typename T>
void insertSort(T arr[], int len){
    int i, j;
    T key;
    for(i = 1; i < len; i++){
        key = arr[i];
        // 当前 key 依次与前导有序列表元素比较, 前导大则后挪
        for(j = i; j > 0; j--)
            if(arr[j - 1] > key)
            // 当前 = 前导, 表示前导元素朝后挪动
                arr[j] = arr[j - 1];
            else
                break;
        // 插入 key
        arr[j] = key;
        // 打印这一轮排序结果
        print<T>(arr, len);
    }
}


int main(){

    char chs[] = {'b', 'a', 'v', 'h', 'j', 'i'};
    int vals[] = {12, 5, 2, 250, 135, 111};

    // before
    std::cout << "before\n";
    print<char>(chs, sizeof(chs)/sizeof(char));
    print<int>(vals, sizeof(vals)/sizeof(int));

    insertSort<char>(chs, sizeof(chs)/sizeof(char));
    insertSort<int>(vals, sizeof(vals)/sizeof(int));

    // after
    std::cout << "after\n";
    print<char>(chs, sizeof(chs)/sizeof(char));
    print<int>(vals, sizeof(vals)/sizeof(int));

    return 0;
}

insertSort

  • 时间复杂度 最坏(逆序) - O(n*n), 最好(一次都没挪动)O(n)

冒泡排序

// 冒泡
template <typename T>
void bubbleSort(T arr[], int len){
    bool swapped;
    for(int i = 0; i < len; i++){
        swapped = false;
        for( int j = 0; j < len - i - 1; j++){
            if(arr[j] > arr[j+1]){
                std::swap(arr[j], arr[j+1]);
                swapped = true;
            }
        }
        print<T>(arr, len);
        // 如果这一轮没有交换, 说明每个元素总是不大于后继元素, 不需要再交换了
        if(!swapped)
            break;
    }
}
  • 时间复杂度 最坏(逆序) - O(n*n), 最好(一次都没交换, 比较了n-1次)O(n)

选择排序

选择排序与插入排序一样, 也是需要将一个序列分为前段已排序序列后段未排序序列. 只不过选择排序是在迭代循环中不停的从后段选择最小(升序)或最大(降序)元素放置到前段已排序序列尾部; 而插入排序不选择后段特定元素, 而是依次将后段中的每一个元素插入到前段已排序序列中适当位置.

例子

// 考虑数组 [22, 11, 33, 66, 55]
// 升序
// 第一次: 在索引 [0...4] 中选择最小元素, 放到前段尾部, 前段还没有, 放到开头
[11], [22 33 66 55]
// 第二次: 在索引 [1...4] 中查找最小元素, 放到前段尾部
[11 22], [33 66 55]
// 第三次: 在索引 [2...4]......
[11 22 33], [66 55]
// 第四次: 在索引[3...4]......
[11 22 33 55], [66]
// 第五次: 
[11 22 33 55 66]

一个C++实现(降序)

#include <iostream>
#include <algorithm>
#include <string>

// 打印列表
template<typename T>
void print(T arr[], int len){
    using namespace std;
    for(int i = 0; i < len; cout << arr[i] << " ", i++);
    cout << endl;
}

// 选择排序
template <typename T>
void selectSort(T arr[], int len){
    int i, j, k; // k 为未排序子序列中的最大值的索引
    for(i = 0; i < len - 1; i++){
        // 在子序列中找最大, 记录最大值索引
        k = i;
        for(j = i + 1; j < len; j++)
            if(arr[j] > arr[k])
                k = j;

        // 将最大值交换至当前位置
        if(arr[i] < arr[k])
            std::swap(arr[i], arr[k]);
        print(arr, len);
    }
}

int main(){

    using namespace std;
    int arr[] = {22, 11, 44, 33, 55};
    string strs[] = {"hello", "baby", "world", "love"};

    // 排序前
    cout << "排序前\n";
    print(arr, 5);
    print(strs, 4);
    // 排序中
    cout << "排序中\n";
    selectSort(arr, 5);
    selectSort(strs, 4);
    // 排序后
    cout << "排序后\n";
    print(arr, 5);
    print(strs, 4);

    return 0;
}

selectionSort

  • 时间复杂度 O(n*n)(两个嵌套for);
  • 空间复杂度 O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值