简单易懂排序算法(一)【冒泡排序】

08月10日 收藏 0 评论 2 IT互联网

简单易懂排序算法(一)【冒泡排序】

转载声明:文章来源https://blog.csdn.net/qq_38790716/article/details/85929469

冒泡排序:一种交换排序,基本思想是两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止

1.容易理解的代码:

void BubbleSort(vector<int>& vec)
{
int n = vec.size();
for (int i = 0; i < n - 1; ++i)
{
for (int j = i + 1; j < n; ++j)
{
if (vec[i] > vec[j])
swap(vec[i], vec[j]);
}
}
}

(在这里我们传入向量的引用,可以直接改变v e c t o r vectorvector的值,后续也是如此应用)
上述代码理解起来还是比较简单的,但效率非常低,可以以一个简单的例子来测试一下:
初始序列:9,1,5,8,3,7,6,2

可以看到在第二次排序之后3被换到了最后面,即在排好了1和2的位置后,对于其他关键字的排序并没有什么帮助,由此可以看出这个算法的效率非常低。

2.标准的冒泡排序

void BubbleSort(vector<int>& vec)
{
int n = vec.size();
for (int i = 0; i < n; ++i)
{
for (int j = n - 2; j >= i; --j) //注意j是从后往前循环
{
if (vec[j] > vec[j + 1])
swap(vec[j], vec[j + 1]);
}
}
}

还是以上述例子来进行测试:
初始序列:9,1,5,8,3,7,4,6,2

可以看到每一次排序过后最小的值都到了指定的位置,同时我们与上一个算法比较一下,即在第二次排序之后,上一个算法中3到了最后面,而在这个算法中3、4都较之前的序列往前进了,这种差异在小序列可能并不是很明显,但当序列足够大时这种差异就会体现出来。

从结果可以看到,每一个较小的数字像气泡一样慢慢浮到了前面,因此也被称为冒泡排序

3.改进的冒泡排序
在给出的序列已基本有序的情况下,例:2,1,3,4,5,6,7,8,9
简单测试一下:

可以看到,在序列基本有序的情况下,在第一次排序后就已经完全有序,但此时算法仍在不断的进行循环判断,这种无意义的循环判断明显的降低了效率,因此,为了减少这种无意义的判断,我们可以将算法作如下改进:

void BubbleSort(vector<int>& vec)
{
int n = vec.size();
bool flag = 1;
for (int i = 0; i < n && flag; ++i)
{
flag = 0;
for (int j = n - 2; j >= i; --j)
{
if (vec[j] > vec[j + 1]) {
swap(vec[j], vec[j + 1]);
flag = 1; //有交换则置为1
}
}
}
}

结果如下:

可以看到明显的减少了无意义的循环判断,再来简单分析一下代码的改动:

代码改动的关键在于i变量的for循环中,增加了对flag是否为1的判断,经过这样的判断,就能知道代码是否有序,因为如果有序的话则flag为false直接跳出循环.

冒泡排序时间复杂度分析

简单分析一下时间复杂度。在最好的情况下,也就是要排序的表本身是有序的,根据我们改进的代码,可以得出经过n − 1 n-1n−1次的比较,没有数据交换,时间复杂度为O(n)
在最坏的情况下,即待排序表是逆序的情况下,此时需要比较

并作等数量级的记录移动。
因此,总的时间复杂度为O(n^2)
一种稳定的排序算法

测试代码:

#include <iostream>
#include <vector>
using namespace std;

void BubbleSort(vector<int>& vec);
void PrintStep(vector<int> vec, int n, int i);
void PrintResult(vector<int> vec, int n);

void BubbleSort(vector<int>& vec)
{
cout << "--------------冒泡排序--------------" << endl;
int n = vec.size();
bool flag = 1;
for (int i = 0; i < n && flag ; ++i)
{
flag = 0;
for (int j = n - 2; j >= i; --j)
{
if (vec[j] > vec[j + 1]) {
swap(vec[j], vec[j + 1]);
flag = 1;
}
}
PrintStep(vec, n, i);
}
cout << "最终排序结果为:";
PrintResult(vec, n);
}

void PrintStep(vector<int> vec, int n, int i)
{
cout << "第" << i + 1 << "次排序结果: ";
for (int j = 0; j < n; ++j)
cout << vec[j] << ' ';
cout << endl;
}

void PrintResult(vector<int> vec, int n)
{
for (int j = 0; j < n; ++j)
cout << vec[j] << ' ';
cout << endl;
}
int main(int argc, char **argv)
{
int a[] = {2,1,3,4,5,6,7,8,9};
vector<int > vec(a, a+9);
BubbleSort(vec);
return 0;
}





C 2条回复 评论
小朱吖

我没有实习,也没有赶上校招,毕业之后只能社招,投的简历全部石沉大海,特别受打击。开始反思,找问题。简历做的不够好,产品质量达不到。现在停下来,在开始系统的,查漏补缺的学习。

发表于 2022-09-03 21:00:00
0 0
Yolk

我的java个人心得,入门重要,但是大多 数人都搞错了方向: 第一.切记不要一上来就找一大本厚书看。 这样你绝对会放弃。《Java核心技术》 《Java编程思想》 等都不适合入门阅读,很容易半途而废。 第二.先找一个入门级别的java教程看。 网上有很多极简入门教程。 例如runoob网站、w3cschool网站(它还有手机app) (上网搜一下关键词就有了)。 我记得我一开始入门找的教程,知识面全而精炼简洁, 含有基础、spring、Hibernate Servlet 等,地址如下仅供参考。 How2J 的 Java教程 第三.当你学完刚才那些网站之后, 你应该此时对java有了一个整体的认识, 那就去找一个小项目,GitHub很棒, https://github.com/上手练习,边做项目边查资料。 进步会飞快。 第四.这个阶段再回头精读一些java经典书籍。 获得内功上的提升。总之,一定要循序渐进, 一点点学才是最正确的选择。个人愚见,仅供参考

发表于 2021-09-11 17:45:00
0 0