排序算法合集

冒泡排序

从序列的右边开始比较相邻的两个数字的大小,再根据比较结果交换两个数字的位置
时间复杂度:O( n 2 n^2 n2)

vector<int> BubberSort(vector<int> &vecData)
{
    for (size_t i = 0; i < vecData.size(); i++)
    {
        for (size_t j = 0; j < vecData.size()-i; j++)
        {
            if (vecData[j-1] > vecData[j])
            {
                Swap(vecData[j-1], vecData[j]);
            }
        }
        
    }
    return vecData;
}

选择排序

从待排序的数据中找到最小值,将其与序列最左侧的数字进行交换
时间复杂度:O( n 2 n^2 n2)

vector<int> SelectSort(vector<int> &vecData)
{
    for (size_t i = 0; i < vecData.size(); i++)
    {
        int iSelect = i;
        for (size_t j = i+1; j < vecData.size(); j++)
        {
            if (vecData[j] < vecData[iSelect])
            {
                iSelect = j;
            }
        }
        if (iSelect != i)
            Swap(vecData[i], vecData[iSelect]);
        
    }
    return vecData;
}

插入排序

一种从序列左端开始依次对数据进行排序的算法,左侧的数据陆续归位,右侧数据是待排序的数据(有点像部分冒泡)
时间复杂度:O( n 2 n^2 n2)

vector<int> InsertSort(vector<int> &vecData)
{
    for (size_t i = 1; i < vecData.size(); i++)
    {
        for (size_t j = i; j > 0; j--)
        {
            if (vecData[j] < vecData[j-1])
            {
                Swap(vecData[j], vecData[j-1]);
            }
        }
    }
    return vecData;
}

堆排序

通过最大堆或最小堆,每次取出堆顶,对剩余节点进行堆调整,直到整个堆取完。

采用一维数组表示完全二叉树,假设当前节点为i,则其父节点为(i-1)/2取下整,左右子节点分别为2i+1和2i+2

时间复杂度:O( n l o g n nlogn nlogn),每轮取出最大的数据并重构堆所需时间为O( l o g n logn logn),总共需要进行n轮

基本思想

  • 将无序序列建成一个堆
  • 输出堆顶元素
  • 以最后一个元素代替堆顶元素
  • 将剩余的n-1个元素再调整成一个堆
  • 重复执行,直到整个堆剩一个元素
void HeapAdjust(vector<int> &vecData, int index, int nLen)
{
    int max = index;
    int lchild = 2*index+1; //左子节点
    int rchild = 2*index+2; //右子节点

    //找出当前调整节点与子节点中的最大值
    if (lchild < nLen && vecData[lchild] > vecData[max])
        max = lchild;
    
    if (rchild < nLen && vecData[rchild] > vecData[max])
        max = rchild;
    
    if (index != max) //需要调整
    {
        Swap(vecData[index], vecData[max]); //调整以后,被调整的子节点也需要进行递归调整
        HeapAdjust(vecData, max, nLen);
    }
}

vector<int> HeapSort(vector<int> &vecData)
{
    int n = vecData.size();
    for (int i = n/2-1; i>=0; i--)
    {
        HeapAdjust(vecData, i, n);
    }

    for(int i = n - 1; i>=0; i--)
    {
        Swap(vecData[0], vecData[i]); //把最大堆的最大值放到最后一个
        HeapAdjust(vecData, 0, i);    //那么需要调整的就剩下n-1个
    }
    return vecData;
}

归并排序

把序列分成长度相同的两个字序列,当无法继续往下分时,就对子序列进行归并
分治法,分解成子问题,再分别解决问题,再归并
时间复杂度O( n l o g n nlogn nlogn)

void Merge(vector<int> &vec, int start, int mid, int end)
{
    vector<int> vecTmp;
    int i = start;
    int j = mid+1;
    while (i <= mid && j <= end)  // 因为最终拆分到只剩一个,需要取等号
        vecTmp.push_back(vec[i]<vec[j]? vec[i++]:vec[j++]);

    while(i<=mid)
        vecTmp.push_back(vec[i++]);

    while(j<=end)
        vecTmp.push_back(vec[j++]);

    for (int k =0; k < vecTmp.size(); k++) //将排序后到临时缓冲区替换原始数组中正在排序的部分
        vec[start+k] = vecTmp[k];
}
void MergeSort(vector<int> &vec, int start, int end)
{
    if (start>=end)
        return;
    int mid = (start+end)/2;
    MergeSort(vec, start, mid);  //分治
    MergeSort(vec, mid+1, end);
    Merge(vec, start, mid, end); //合并
}
vector<int> MergeSort(vector<int> &vecData)
{
    MergeSort(vecData, 0, vecData.size());
    return vecData;
}

快排

首先在序列中随机选择一个基准值,将小于基准的数排到左侧,大于基准的拍到右侧
时间复杂度O( n l o g n nlogn nlogn),如果每次选择的值都是最小值作为基准,则为O( n 2 n^2 n2)

nt Partition(vector<int> &vecData, int lhs, int rhs)
{
    int key = vecData[lhs];
    while(lhs < rhs)
    {
        while (lhs<rhs && vecData[rhs] <= key)
            rhs--;
        if (lhs < rhs)
            vecData[lhs] = vecData[rhs];
        
        while(lhs < rhs && vecData[lhs] >= key)
            lhs++;
        
        if (lhs<rhs)
            vecData[rhs] = vecData[lhs];
    }
    return lhs;
}
void QuickSort(vector<int> &vecData, int lhs, int rhs)
{
    if (lhs >= rhs)
        return;
    int i = Partition(vecData, lhs, rhs);
    QuickSort(vecData, lhs, i);
    QuickSort(vecData, i+1, rhs);
}

vector<int> QuickSort(vector<int> &vecData)
{
    QuickSort(vecData, 0, vecData.size()-1);
    return vecData;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值