基础篇——常见排序算法总结(一)冒泡算法
新人小白学习和总结一下常见的排序算法。
排序算法分类
按照排序过程中数据的保存形式的不同,可将排序分为内部排序和外部排序两大类。
如果排序过程不需要访问外存,就称之为内部排序(外存也就是计算机配备的存储容量更大的磁盘存储器和光盘存储器)。其实,所有排序过程都是在内存里面做的,但是外部排序需要做与外界的内外存交换,也就是说,内部排序消耗的是时间复杂度,外部排序消耗的是空间复杂度。当待排序的文件很大时,计算机内存不够大,所以需要进行内外存交换。
网上盗图如下:
排序算法的稳定性
排序的过程中,会碰到如下情况,比如当排序的俩个数值相等时,比如序列{2,5,8,2,3,2},如果排序后这些元素2的相对位置不变,即对于一个已经排序好的序列{2,2,2,3,5,8},排序算法还会不会改变上述元素的相对位置,如果不改变的话,那这个算法是稳定的,否则是不稳定的。
常见排序算法如下:
稳定的排序算法有:插入排序、冒泡排序、归并排序和基数排序。
快排、希尔、选择排序和堆排序是不稳定的算法。
1.冒泡算法(所学第一个排序算法)
#include<iostream>
int main()
{
int a[10] = { 2,12,5,6,1,2,25,11,254,12};
int swap = 0;
//冒泡从小到大排序
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9 - i; j++)
{
if (a[j] > a[j + 1])
{
swap = a[j + 1];
a[j + 1] = a[j];
a[j] = swap;
}
}
for (int i = 0; i < 10; i++)
std::cout << a[i] << "\n";
//冒泡从大到小排序
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9 - i; j++)
{
if (a[j] < a[j + 1])
swap = a[j];
a[j] = a[j + 1];
a[j + 1] = swap;
}
for (int i = 0; i < 10; i++)
std::cout << a[i] << "\n";
return 0;
}
光看是没用的,还得自己写,光是这个排序我还出了不少错误。。。。。。
时间复杂度O(n的平方)
最大时间复杂度1+2+3+…+(n-1)(判断一次(包括判断后的执行语句)算一次运算)
所以:最坏时间复杂度为O(n^2)
然而,根据资料显示,冒泡算法的最好时间复杂度为O(n),但是正序情况下难道不是也要比较O(n^2)次么,按照上述的我写的冒泡算法确实不是O(n),但是可以做一个小改进,就是如何在所有的排序顺序都对的时候,返回一个值,终止循环?
int main(){
int a[10] = { 2,12,5,6,1,2,25,11,254,12 };
int swap = 0;
bool choice=true;
//改进冒泡算法
for (int i = 0; i < 9; i++)
{ for (int j = 0; j < 9 - i; j++)
choice = true;
if (a[j] > a[j + 1])
{
swap = a[j + 1];
a[j + 1] = a[j];
a[j] = swap;
choice = false;
}
//如果经过一次冒泡过程,没发生交换
if (choice == true)
return 0;
}
1.2定向冒泡算法
为了改进冒泡算法,提出了定向冒泡算法(鸡尾酒排序)
为什么叫鸡尾酒排序呢,因为这种改进算法是气泡从左到右,得到序列尾部的最大值后,又从右到左,可以得出头部的最小值。鸡尾酒是需要不断翻转的,这种比喻很生动。
int main(){
int a[10] = { 2,12,5,6,1,2,25,11,254,12 };
//如果是10个数 则最多4个来回确定4个最小的和4个最大的数 ,然后再进行一次比较
//如果按n分成奇数偶数感觉好麻烦 就做2*int((n+1)/2)次循环比较
int swap = 0;
for (int j = 0; j < 10 - 1; j++)
{
if(j % 2 == 0 && j < (10 - 1)) //i为偶数 从左到右排序
for (int i = 0; i < 9 - j; i++)
{
if (a[i] > a[i + 1])
{
swap = a[i];
a[i] = a[i + 1];
a[i + 1] = swap;
}
}
if( j % 2 == 1 && j < 9) //i为奇数,从右往左排序
for (int i = 9 - j; i > 0; i--)
{
if (a[i] < a[i - 1])
{
swap = a[i];
a[i] = a[i - 1];
a[i - 1] = swap;
}
}
}
下面是加了标记后的鸡尾酒算法
int main()
{
int a[10] = { 2,12,5,6,1,2,25,11,254,12 }
//如果是10个数 则最多4个来回确定4个最小的和4个最大的数 ,然后再进行一次比较
//如果按n分成奇数偶数感觉好麻烦 就做2*int((n+1)/2)次循环比较
bool choice = false;
int swap = 0;
for (int j = 0; j < 10 - 1; j++)
{
choice = true;
if(j % 2 == 0 && j < (10 - 1)) //i为偶数 从左到右排序
for (int i = 0; i < 9 - j; i++)
{
if (a[i] > a[i + 1])
{
swap = a[i];
a[i] = a[i + 1];
a[i + 1] = swap;
choice = false;
}
}
if( j % 2 == 1 && j < 9) //i为奇数,从右往左排序
for (int i = 9 - j; i > 0; i--)
{
if (a[i] < a[i - 1])
{
swap = a[i];
a[i] = a[i - 1];
a[i - 1] = swap;
choice = false;
}
}
if (choice == true)
return 0;
}
for (int i = 0; i < 10; i++)
std::cout << a[i] << "\n";
return 0;
}
定向冒泡排序,能稍稍增加排序算法的性能,但总的来说效率不高。
本人水平比较差,欢迎批评指正~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本