十大排序算法

冒泡排序

/*
 * 冒泡排序
 * 依次比较左右两个元素的大小,如果左边的元素大于右边,那么两者交换位置
 * 在第一次的比较过程,将所有元素的最大元素放置最后一个位置
 * 后续依次将第二大元素放置倒数第二,第三大放置倒数第三...
 * 时间复杂度:最坏情况o(n^2) 最好情况o(n)
 * 空间复杂度:o(1),只需要一个额外空间
 * 稳定的排序算法
 * */
void bubblesort(vector<int>&ans)
{
    int n = ans.size();
    for(int i = 0;i<n;i++)
    {
        for(int j = 0;j<n-i-1;j++)
        {
            if(ans[j]>ans[j+1])
            {
                swap(ans[j],ans[j+1]);
            }
        }
    }
}

插入排序

/*
 * 插入排序
 * 通过构建有序序列,对于未排序的数据,可以从有序数列中从后往前查找,找到相应位置并插入
 * 从第一个元素开始,可以看成是已排序数据
 * 取出下一个元素,从已排序数据中从后往前查找
 * 如果已排序数据中某个元素大于新元素,那么就新元素插入这个元素之前
 * 重复步骤三,直至找到已排序数据中小于或等于新元素的位置
 * 将新元素插入该位置后
 *  时间复杂度:平均 o(n^n) 最好情况o(n)
 *  空间复杂度 o(1)
 *  稳定的排序算法
 * */
void insertion_sort(vector<int>& ans)
{
    int i,j,key;
    int n = ans.size();
    for(i = 1;i<n;i++)
    {
        if(ans[i]>ans[i-1])
        {
            continue;
        }
        key = ans[i];
        j = i-1;
        while(j>=0 &&(ans[j]>key))
        {
            ans[j+1] = ans[j];
            j--;
        }
        ans[j+1] = key;
    }
}

希尔排序

/*
 * 希尔排序
 * 将待排序序列按照一定的增量,分为若干个组,对每个组实行直接插入排序
 * 随着增量的减少,每组包含的元素越来越多,同样对每个组实行直接插入排序
 * 当增量为1时,所有元素被分为一组,再实现直接插入排序,算法终结
 * 时间复杂度:平均o(nlogn)  最坏 o(n^n)
 * 空间复杂度: o(1)
 * 不稳定的排序算法
 * */
void Shellsort(vector<int>& ans)
{
    int count = 1;

    int n = ans.size();
    for(int i = n/2;i>0;i/=2)
    {
        //循环分治每一个分组
        for(int j = i;j<n;j++)
        {
            int index =j;
            int temp = ans[index];
            if(ans[index]<ans[index-i])
            {
                while((index-i)>=0 && temp<ans[index-i])
                {
                    ans[index] = ans[index-i];
                    index-=i;
                }
                ans[index] = temp;
            }
        }
    }
}

选择排序

/*
 * 选择排序
 * 首先在未排序序列中找到最小(大)的元素,放到序列的起始位置
 * 接着找到未排序序列中的最小元素,放到已排序序列的末尾
 * 重复第二步,直到全部元素排序
 * 时间复杂度:任何情况 o(n^2)
 * 不稳定
 * */
void select_sort(vector<int>& ans)
{
    int n = ans.size();
    for(int i = 0;i<n;i++)
    {
        int min_value = ans[i];
        int k = i;
        for(int j = i+1;j<n;j++ )
        {
            if(ans[j]<min_value)
            {
                min_value = ans[j];
                k = j;
            }
        }
        swap(ans[i],ans[k]);
    }
}

归并排序

//已排序部分合并
void merge(vector<int>& ans,vector<int>& tempArr,int left,int right,int mid)
{
    //标记左半区未被排序的第一个元素
    int l_pos = left;
    //标记右半区未被排序的第一个元素
    int r_pos = mid+1;
    //临时数组元素的下标,要从该区域的最左边起开始合并
    int pos = left;

    while(l_pos<=mid && r_pos<=right)
    {
        if(ans[l_pos]<=ans[r_pos])
            tempArr[pos++] = ans[l_pos++];//左边的第一个元素比右边第一个的元素小
        else
            tempArr[pos++] = ans[r_pos++];//右边的第一个元素比坐边第一个的元素小
    }
    //合并左半区剩余元素
    while(l_pos<=mid)
    {
        tempArr[pos++] = ans[l_pos++];
    }
    //合并右半区剩余元素
    while(r_pos<=right)
    {
        tempArr[pos++] = ans[r_pos++];
    }

    while(left<=right)
    {
        ans[left] = tempArr[left];
        left++;
    }
}
//归并排序
void msort(vector<int>& ans,vector<int>& tempArr,int left,int right)
{
    //如果只有一个元素,就没有必要再继续分
    //只有一个元素的区域,本身就是有序的,只需要等着被归并即可
    if(left<right)
    {
        //中间位置
        int mid = (left+right)/2;
        //递归划分左半区
        msort(ans,tempArr,left,mid);
        //递归划分右半区
        msort(ans,tempArr,mid+1,right);
        //合并已经排好序的部分
        merge(ans,tempArr,left,right,mid);
    }
}
/*
 * 归并排序是一种分治的思想,将大问题拆解成小问题,将一个大的数组先拆分成小子数组,另子数组内是有序的,再将有序的子数组合并,得到完全有序的序列
 * 时间复杂度:任何情况都是o(nlogn)
 * 空间复杂度:o(n)  在归并排序中需要额外辅助数组
 * 稳定的排序算法
 * */
//归并函数入口
void MergeSort(vector<int> &ans)
{
    int n =ans.size();
    vector<int> tempArr(10);
    msort(ans,tempArr,0,n-1);
}

快速排序

/*
 * 快速排序
 * 从待排序数列中找一个元素作为基准
 * 将所有比基准小的元素放到它的前面,所有比基准大的元素放在它后面。这个时候基准就到了它该在的位置
 * 然后递归的将大于 和 小于基准的子序列进行排序
 * 时间复杂度:o(nlogn)
 * 空间复杂度:o(1)
 * 不稳定
 * */
void msort(vector<int>& ans,int left,int right)
{
    //一个元素的情况下,默认有序
    if(left>=right)
    {
        return;
    }
    int i = left;
    int j = right;

    int baseval = ans[left];

    while(i<j)
    {
        //从后往前,找到比baseval小的值
        while(i<j&&ans[j]>=baseval)
        {
            j--;
        }
        if(i<j)
        {
            ans[i] = ans[j];
            i++;
        }

        //从前往后,找比基准大的值
        while(i<j && ans[i]<baseval)
        {
            i++;
        }
        if(i<j)
        {
            ans[j] = ans[i];
            j--;
        }
    }

    ans[i] = baseval;

    msort(ans,left,i-1);
    msort(ans,i+1,right);
}
//快速排序的入口
void quicksort(vector<int>& ans)
{
    int n = ans.size();
    msort(ans,0,n-1);

}

堆排序

/*
 * 维护堆的性质
 * @param ans存储堆的数组
 * @param 数组长度
 * @param 待维护结点的下标
 * 在堆排序中,一般是用数组存储堆
 * 因此数组位置为i的元素,那么它的左孩子在i*2+1位置  右孩子在i*2+2位置
 * 数组位置为i的元素,它的父节点在(i-1)/2
 * */
void heafify(vector<int>& ans,int n,int i)
{
    int largest = i;
    int lson = i*2+1;
    int rson = i*2+2;

    if(lson<n && ans[largest]< ans[lson])
        largest=lson;
    if(rson<n && ans[largest]<ans[rson])
        largest = rson;

    //如果子节点比父节点大
    if(largest!=i)
    {
        //交换两者的位置
        swap(ans[i],ans[largest]);

        //此时继续维护交换过位置的子堆
        heafify(ans,n,largest);
    }
}
/*
 * 堆排序是一种利用堆所设计的排序算法
 * 首先将待排序序列构建成大顶堆,此时堆是无序区
 * 将堆顶元素和最后一个元素交换,得到新的无序区和新的有序区
 * 由于新交换后的堆不满足大顶堆的性质,需要对新的堆重新构建为打定堆,然后再将堆顶元素和最后一个元素交换,得到新的无序区和新的有序区
 * 不断重复此过程,指导有序区的元素个数为n-1,也就是所有元素有序
 * */
void heaf_sort(vector<int>& ans)
{
    int n = ans.size();
    //建堆
    for(int i = (n/2)-1;i>=0;i--)
    {
        heafify(ans,n,i);
    }

    //排序
    for(int i = n-1;i>0;i--)
    {
        swap(ans[i],ans[0]);
        //因为第一次的时候,最后一个元素就有序,所以从N-1开始
        heafify(ans,i,0);
    }
}

计数排序

/*
 * 计数排序
 * 找出待排序数组中的最大值N
 * 构建一个N+1大小的额外空间tempArr
 * 统计待排序数组中元素出现的次数,纪录在额外空间中
 * 对额外空间中的每个元素依次累加
 * 反向填充数组,遍历待排序数组中元素,看它在tempArr[该元素]的大小,将它放在结果序列的该位置,tempArr[该元素]--
 * 得到的结果就是有序序列
 *
 * 计数排序不是比较排序,它的时间复杂度是线性的
 * 时间复杂度: o(n+k)  待排序序列是n个0到k之间的整数
 * 计数排序对空间的占用比较多,所以对于数据范围很大的数组不合适
 * 稳定排序算法
 * */
void count_sort(vector<int>& ans)
{
    int len = ans.size();
    if(len<=1)
    {
        return;
    }

    int max_value = 0;
    for(auto a:ans)
    {
        max_value = max(a,max_value);
    }

    vector<int> tempArr(max_value+1);

    for(auto a:ans)
    {
        tempArr[a]++;
    }

    for(int i = 1;i<=max_value;i++)
    {
        tempArr[i]+=tempArr[i-1];
    }

    vector<int> output(len);

    for(auto a:ans)
    {
        output[--tempArr[a]] = a;
    }

    for(int i = 0;i<len;i++)
    {
        ans[i] = output[i];
    }

}

桶排序

/*
 * 桶排序
 * 假定数组中元素服从均匀分布
 * 按照一定的规则,创建一定数量的桶
 * 将元素按照范围,依次放到对应的桶中
 * 对桶中的元素进行排序(任何排序算法都行)
 * 在将桶中的元素连接到一块
 * 算法时间复杂度 o(n+k) n个数据分到k个桶中
 * 空间复杂度 o(n+k)
 * 稳定
 * */
void bucket_sort(vector<int>& ans)
{
    int n = ans.size();
    int max_value = 0;

    for(auto a:ans)
    {
        max_value = max(a,max_value);
    }

    vector<int> tempArr1;
    vector<int> tempArr2;
    vector<int> tempArr3;
    vector<int> tempArr4;

    for(auto a:ans)
    {
        if(0<=a&& a<=max_value/4)
        {
            tempArr1.push_back(a);
        }
        else if((max_value/4)<a && a<=(2*max_value/4))
        {
            tempArr2.push_back(a);
        }
        else if((2*max_value/4)<a && a<=(3*max_value/4))
        {
            tempArr3.push_back(a);
        }
        else
        {
            tempArr4.push_back(a);
        }
    }



    count_sort(tempArr1);

    count_sort(tempArr2);

    count_sort(tempArr3);

    count_sort(tempArr4);

    ans.clear();
    for(auto a:tempArr1)
    {
        ans.push_back(a);
    }
    for(auto a:tempArr2)
    {
        ans.push_back(a);
    }
    for(auto a:tempArr3)
    {
        ans.push_back(a);
    }
    for(auto a:tempArr4)
    {
        ans.push_back(a);
    }

}

基数排序

/*
 * 基数排序
 * 基数排序是桶排序的扩展
 * 首先确定数组中最大元素有几位
 * 创建0-9这10个桶,每个数组都是0-9组成
 * 按照数字的位数,依次存放到对应的桶中
 * 按照队列的方式依次将桶中的元素取出
 * 接着继续执行上一步骤
 * 时间复杂度o(n*k)
 * 空间复杂度o(n+k)
 * 稳定
 * */
void mysort(vector<int>&ans,int n,int exp)
{
    vector<int> output(n);

    vector<int> bucket(10);

    for(auto a:ans)
    {
        bucket[(a/exp)%10]++;
    }

    for(int i = 1;i<10;i++)
    {
        bucket[i]+=bucket[i-1];
    }

    for(int i = n-1;i>=0;i--)
    {
        output[bucket[(ans[i]/exp)%10]-1] = ans[i];
        bucket[(ans[i]/exp)%10]--;
    }

    for(int i = 0;i<n;i++)
    {
        ans[i] = output[i];
    }
}
int getMax(vector<int>&ans)
{
    int n = ans[0];
    for(auto a:ans)
    {
        n = max(n,a);
    }

    return n;
}
void radix_sort(vector<int>&ans)
{
    int n = ans.size();
    int max_value = getMax(ans);
    for(int exp=1;max_value/exp>0;exp*=10)
    {
        mysort(ans,n,exp);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值