Algorithm5——排序算法

本系列算法实现都是在学习数据结构(C++语言版),清华大学邓俊辉教授编,听邓老师edX网课过程中自己实现的例子。

问题:对一组无顺序向量进行排序,使得按<排列
解决:用常见的排序算法解决,有如下几种

  • 冒泡排序
  • 选择排序
  • 归并排序
  • 快速排序
  • 堆排序

参考链接:
* 排序算法可视化——visualgo
* 排序算法wiki
* Jark’s Blog——经典排序算法总结与实现

0 各种排序算法的比较

表格来自wiki
这里写图片描述
这里写图片描述

1 冒泡排序

这里给出的冒泡排序是优化后的,主要思想是从左到右依次扫描,如果相邻是逆序对,则交换,这样最多经过N-1次(N是元素个数)就能排序完成。
其是平均时间复杂度为O(n^2)

//! name : 起泡排序
//! brief: sort elems in array[low, high) by <
//! time : O(n^2)
//! stability: STABLE
template <typename T>
void bubble_sort(T& array, int low, int high)
{
    int last = 0;//mark 最右侧逆序对位置
    while (low < high)
    {
        last = low;

        while (++low < high)
        {
            if (array[low - 1] > array[low])// > not the >= , make this algorithm stable
            {
                last = low;
                std::swap(array[low - 1], array[low]);
            }
        }
        low = 0;
        high = last;//最右侧逆序对位置
    }
}

2 选择排序

选择排序的思路是从左到右扫描,每次扫描找到最小元素,然后追加到有序区后面。算法时间复杂度为O(n^2)

//! name : 选择排序
//! brief: sort elems in array[low, high) by <
//! time : O(n^2)
//! stability: UNSTABLE
template <typename T>
void select_sort(T& array, int low, int high)
{
    int min;
    for (int i = low; i < high; ++i)//traversal elem
    {
        min = i;
        for (int j = i + 1; j < high; ++j)
        {
            if (array[min] > array[j])
            {
                min = j;
            }
        }
        std::swap(array[min], array[i]);
    }
}

3 归并排序

归并排序的优点是时间复杂度低,为O(NlogN), 并且是稳定排序

算法实现分为两个部分,

  • 对无序向量进行递归分解
  • 对有序向量进行逐层归并
3.1 递归分解

首先确定递归分解的递归基

//recursion base
if (high - low < 2)
    return;

算法实现如下

template <typename T>
void merge_sort(T* array, int low, int high)
{
    //recursion base
    if (high - low < 2)
        return;

    int mid = (low + high) >> 1;
    merge_sort(array, low, mid);//[low, mid)
    merge_sort(array, mid, high);//[mid, high)

    merge(array, low, mid, high);
}
3.2 逐层合并
  • 首先申请内存,复制array的第一部分array[low,mid)到tmp[0, mid-low)中
  • 然后逐个比较tmp[0, mid-low)和array[mid, high),较小的放到array[low, high)中
//! name : 归并排序
//! brief: sort elems in array[low, high) by <
//! time : O(NlogN)
//! stability: STABLE
template <typename T>
void merge(T* array, int low, int mid, int high)
{
    T* tmp = new T[mid - low];
    for (int i = 0; i < mid - low; ++i) //copy first part of array
    {
        tmp[i] = array[low + i];
    }

    // i for tmp[i], i = [0, mid-low)
    // j for array[j],j = [mid, high)
    // k for merge, array[k], k = [low, high)
    int i = 0, j = mid, k = low;
    while (k < high)//sorted all
    {
        if (i < mid - low && j < high)
        {
            tmp[i] > array[j] ? array[k++] = array[j++] : array[k++] = tmp[i++];
        }
        else if (i < mid - low && j == high)
        {
            while (i < mid)
            {
                array[k++] = tmp[i++];
            }
        }
        else if (i == mid - low && j < high)
        {
            while (j < high)
            {
                array[k++] = array[j++];
            }
        }
    }

    delete [] tmp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值