常见的排序算法有冒泡排序,简单选择排序,直接插入排序,快速排序,归并排序,堆排序,桶排序等,这篇文章中我们主要分析前五种排序,包括它们的实现,稳定性分析,时间复杂度分析以及空间复杂度分析。
以下都假设给定一个长度为n的数组
1,冒泡排序
在冒泡排序中, 我们从数组的开始进行比较,如果第一个元素大于第二个元素,我们就将两个元素互换,接下来我们比较第二个元素和第三个元素,如果第二个元素大于第三个元素我们就把它们交换,以此类推,每次循环都得到一个最大的数。代码如下:
public void bubblesort(int[] array){
for(int i=0;i<array.length-1;i++)
for(int j=0;j<array.length-i-1;j++){
if(array[j]>array[j+1]){
int tem=array[j];
array[j]=array[j+1];
array[j+1]=tem;
}
}
}
一共循环了(n-1) + (n-2) +(n-3) .....+1次,时间复杂度为O(n^2)。我们仅用了一个变量tem来保存要交换的数据,因此空间复杂度时O(1)。每次比较时两个元素如果相等两个元素的相对位置不变,因此冒泡排序是稳定的。
2,简单选择排序
简单选择排序和冒泡排序看上去真好相反,冒泡排序的每个循环都会找到一个最大数放在数组的后面,而简单选择排序每次都确定一个最小的元素放在最前面。代码如下:
public void selectsort(int[] array){
for(int i=0;i<array.length-1;i++)
for(int j=i+1;j<array.length;j++){
if(array[i]>array[j]){
int tem=array[i];
array[i]=array[j];
array[j]=tem;
}
}
}
和冒泡排序一样一共循环了(n-1) + (n-2) +(n-3) + .....+1次,所以时间复杂度同样为O(n^2)。我们仅用了一个变量tem来保存要交换的数据,因此空间复杂度为O(1)。因为在选择较小元素时,相同元素的相对位置可能发生变化,比如{2,2,1} 第一个2会和1交换位置,因此简单选择排序是不稳定排序。
3,直接插入排序
直接插入排序是每次从右边的无序序列中选择一个元素,插入多左边有序序列的合适位置,过程是从右往左进行的。代码如下:
public void insertsort(int[] array){
for(int i=1;i<array.length;i++)
for(int j=i;j>0;j--){
if(array[j-1]>array[j]){
int tem=array[j-1];
array[j-1]=array[j];
array[j]=tem;
}
}
}
整个过程循环了1 + 2 + 3 +...+(n-1) 次,所以时间复杂度为O(n^2)。我们仅用了一个变量tem来保存要交换的数据,因此空间复杂度为O(1)。因为每次循环我们都是通过从后向前遍历已排序序列,然后插入,此时相等元素依然可以保持原有位置,因此直接插入排序时稳定排序。如果从左往右遍历有序序列,就和选择排序一样,变成一个不稳定排序。我们在实现的时候尽量把算法设计成稳定排序。
前面的三种排序时间复杂度都是O(n^2), 在实际应用中效率不高,下面的这两种排序算法,大大地提高了排序的效率,也是我们解题中经常用到的排序算法。
4,快速排序
在快速排序中,我们随机选择一个元素,然后把数组分为两段,左边的元素都小于这个元素,右边的元素都大于这个元素,然后用同样的方法处理左边的序列和右边的序列,知道整个数组变为有序。我们从代码来分析,代码如下:
public void quick_sort(int s[], int l, int r) {
if (l < r) {
int i = l, j = r, pivot = s[l];
while (i < j) {
while(i < j && s[j] >= pivot)
j--;
if(i < j)
s[i++] = s[j];
while(i < j && s[i] < pivot)
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = pivot;
quick_sort(s, l, i - 1);
quick_sort(s, i + 1, r);
}
}
在平均情况下,快速排序要递归log(n)次,每次都要处理n个元素,所以时间复杂度时O(nlogn)。因为要递归log(n)次,所以要用log(n)的栈来实现递归,所以空间复杂度为O(log n)。在极端的情况下,快排的时间复杂度是O(n^2),例如如果数组本身时倒序的,每次取最小,这样的时间复杂度就是O(n^2),一共循环了(n-1) + (n-2) +(n-3) + .....+1次。在排序过程中,相同大小的元素的相对位置会发生变化,例如{2,2,1}在一次排序后第一个2会和1交换位置,因此快速排序是一个不稳定排序。
5,归并排序
归并排序是采用了分治的思想,每次把数组分成两段,直到子序列的长度为1,每个子序列都是有序的,然后再合并这些有序的子序列,直到整个序列都有序。我们从代码来分析它的时间复杂度以及空间复杂度,代码如下:
//通过递归使每个子序列都有序,然后再将它们合并
public void mergesort(int low,int high)
{
if(low<high)
{
int middle=low+(high-low)/2;
mergesort(low,middle);
mergesort(middle+1,high);
mergepart(low,middle,high);
}
}
public void mergepart(int low, int middle, int high)
{
for(int i=low;i<=high;i++)
{
temparray[i]=array[i];
}
int i=low;
int j=middle+1;
int k=low;
while(i<=middle&&j<=high){
if(temparray[i]<=temparray[j]){
array[k]=temparray[i];
i++;
}else{
array[k]=temparray[j];
j++;
}
k++;
}
while(i<=middle){
array[k]=temparray[i];
i++;
k++;
}
while(j<=high){
array[k]=temparray[j];
j++;
k++;
}
}
}
程序执行过程中,总共递归了log(n)次,每次都要处理n个数据,所以它的时间复杂度为O(nlogn),因为每次都是把子序列分为长度相等的两段,因此它的最坏情况和平均情况的时间复杂度都是O(nlogn)。对于空间复杂度,不同的算法实现空间复杂度也不同。在这个代码实现中,我们用了一个长度为n的辅助数组,每次都把较小的元素放入数组中,最后我们把剩余的元素也放入目标数组中。递归调用了log(n)次,加上我们开辟的长度为n的数组,所以它的空间复杂度为O(n)。对于稳定性,当有序列的左右两子序列合并的时候一般是先遍历左序列,所以左右序列如果有相等元素,处在左边的仍然在前,因此归并排序时稳定的排序.
总结:
冒泡排序: 时间复杂度O(n^2),空间复杂度O(1),稳定排序
简单选择排序: 时间复杂度O(n^2),空间复杂度O(1),不稳定排序
快速插入排序:时间复杂度O(n^2),空间复杂度O(1),稳定排序
快速排序:时间复杂度O(nlogn) 平均情况,O(n^2)最坏情况,空间复杂度O(logn),不稳定排序
归并排序:时间复杂度O(nlogn),空间复杂度要根据算法具体实现来确定,稳定排序
分享到:
相关推荐
python入门-30.寻找列表中只出现一次的数字——寻找单身狗.py
linux优化笔记,配套视频:https://www.bilibili.com/list/474327672?sid=4496133&spm_id_from=333.999.0.0&desc=1
知识付费系统-直播+讲师入驻+课程售卖+商城系统-v2.1.9版本搭建以及资源分享下载,CRMEB知识付费分销与直播营销系统是由西安众邦科技自主开发的一款在线教育平台,该系统不仅拥有独立的知识产权,还采用了先进的ThinkPhp5.0框架和Vue前端技术栈,集成了在线直播教学及课程分销等多种功能,旨在为用户提供全方位的学习体验,默认解压密码youyacaocom
美妆神域-JAVA-基于springBoot美妆神域设计与实现
原生js制作Google粘土logo动画涂鸦代码.zip
golin 扫描工具使用, 检查系统漏洞、web程序漏洞
原生态纯js图片网格鼠标悬停放大显示特效代码下载.zip
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
去水印web端独立版web
原生js制作左侧浮动可折叠在线客服代码.zip
Chrome 谷歌浏览器下载
全新完整版H5商城系统源码 自己花钱买的,亲测可用,需要自行下载 H5商城系统设置是实现商城基本功能的核心部分,涵盖了从网站配置、短信和支付配置,到商品、工单、订单、分站和提现管理等多个模块的设置。以下是详细的设置指南,帮助您快速上手并高效管理商城系统。 测试环境:Nginx+PHP7.0+MySQL5.6 1. 网站配置 设置商城名称、LOGO、标题、联系方式和SEO关键词等,确保商城专业和易于搜索。 2. 短信配置 配置短信接口和模板,用于发送订单通知、验证码等,提升用户体验。 3. 支付接口配置 配置微信、支付宝等支付接口,填写API密钥和回调地址,确保支付流畅。 4. 商品分类管理 对商品进行分类和排序,设置分类名称和图标,便于用户查找商品。 5. 商品管理 添加和管理商品信息、规格、图片等,确保商品信息准确丰富。 6. 工单管理 查看和回复用户工单,记录售后问题,提升用户服务质量。 7. 订单管理 查看订单详情,更新订单状态,支持批量导出,方便订单跟踪。 8. 分站管理 创建不同区域分站,设置权限,统一管理各区域市场。 9. 提现管理
apk安装包
原生js选项卡插件自定义图片滑动选项卡切换.zip
宗教信息佛教佛寺寺庙庵堂相关数据集提供了全国各个地区省市县各个佛教寺庙的详细信息。这些数据不仅包括寺庙的名称和负责人姓名,还涵盖了所属省份、地级市、区县、具体地址、建立日期以及支派类别等关键信息。该数据集整理了超过3万条样本,为研究中国佛教寺庙的分布、历史和文化提供了丰富的第一手资料。这些信息有助于了解佛教在中国的传播和发展,以及寺庙在社会和文化中的作用。数据的整理和提供,对于宗教学、社会学、历史学和文化研究等领域的学者来说,是一个宝贵的资源。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手
简单的 Python 版本管理pyenvpyenv 可让您轻松在多个 Python 版本之间切换。它简单、不引人注目,并遵循 UNIX 传统,即使用单一用途的工具来做好一件事。该项目由rbenv和 ruby-build分叉而来,并针对 Python 进行了修改。pyenv 的作用是什么......允许您根据每个用户更改全局 Python 版本。为每个项目的 Python 版本提供支持。允许您使用环境变量覆盖 Python 版本。一次搜索多个 Python 版本的命令。这可能有助于使用tox跨 Python 版本进行测试。与 pythonbrew 和 pythonz 相比,pyenv没有……依赖于Python本身。pyenv由纯shell脚本制作。不存在Python的引导问题。需要加载到你的 shell 中。相反,pyenv 的 shim 方法通过向你的 中添加目录来工作PATH。管理虚拟环境。当然,你可以自己创建虚拟环境 ,或者使用pyenv-virtualenv 来自动化该过程。目录安装获取 PyenvLinux/UNIX自动安装程序基本
Notepad-v2.20工具,是替代Notepad++的首选工具
原生js随机图片拖拽排序代码.zip
更快、更好、更稳定的Redis桌面(GUI)管理客户端,兼容Windows、Mac、Linux,性能出众,轻松加载海量键值