一、基本原理
顾名思义,就是像冒着泡泡一样,不断的移动元素的位置,两两相邻不停的比较
二、图像化解释
先准备一个数组
就从第零个元素开始进行排序,根据原理,左右两两排序,因为我们以升序作为举例,由于第零个元素是8大于第一个元素7,所以交换位置,见下图
这样就实现了第一次交换,继续向后进行比较,直到后面的数大于等于自己,于是继续比较自己和第二个元素,大于1于是进行交换,这是第二次交换
实现了第二次交换之后,继续增加索引比较发现自身大于第三个元素5于是交换位置,见下图
以此类推直到交换到第七个元素的位置时,准备和第八个元素进行比较,发现此时后面的元素大于自己于是将最大值的索引定为后一个元素,然后继续以第八个元素为中间商继续重复前面的步骤,发现此时数组的长度已经到头了,就说明最大值的为止已经确定了,然后数组长度减一,准备开始下一轮排序
到这里第一轮的排序就结束了 于是就可以准备下一轮的排序了 从这里可以体会到 我们至少需要两个循环,一个是获取到很多轮,每一个元素就是一个轮,在每一轮中需要获得每一个元素,所以这里需要用一个循环
动态展示
三、代码实现
①实现左右比较元素,满足条件则交换位置
for (int n = 0; n < arr.Length - 1; n++)
{
//如果第n个数大于第n + 1个数 那么就要交换位置
if (arr[n] > arr[n + 1])
{
int temp = arr[n + 1];
arr[n + 1] = arr[n];
arr[n] = temp;
}
}
②比较m轮
for (int m = 0; m < arr.Length - 1; m++)
{
}
③将①的代码放入②中即可,即实现了冒泡排序
for (int m = 0; m < arr.Length - 1; m++)
{
for (int n = 0; n < arr.Length - 1; n++)
{
//如果第n个数大于第n + 1个数 那么就要交换位置
//第二步 交换相邻元素位置
if (arr[n] > arr[n + 1])
{
int temp = arr[n + 1];
arr[n + 1] = arr[n];
arr[n] = temp;
}
}
}
到这里其实就已经完成了冒泡排序
四、代码优化
考虑到两种优化
①既然每次最后的元素都是已经比较完成的元素,也就是说其余的元素不用再和他们继续比较,所以,每比较的轮数就可以减少一些,具体减少多少呢 实际上当我们完成了多少元素的排序之后 实际上就可以减少多少轮 即m轮 故代码可以优化成下面所示
确定了一轮的极值(最大或最小)已经放在了对应的位置(往后放)
所以每完成n轮 后面位置的数不用再比较了
for (int m = 0; m < arr.Length - 1; m++)
{
for (int n = 0; n < arr.Length - 1 - m; n++)
{
//如果第n个数大于第n + 1个数 那么就要交换位置
//第二步 交换相邻元素位置
if (arr[n] > arr[n + 1])
{
int temp = arr[n + 1];
arr[n + 1] = arr[n];
arr[n] = temp;
}
}
}
②考虑到数组本身就是一个有序的状态 不需要我们额外进行排序 所以进行一个比较 只要在一轮完成比较后 元素的位置并没有发生变化 说明 数组自身已经是有序的了 就不再需要排序了 代码可以修改为如下所示
bool isSort = false;
for (int m = 0; m < arr.Length - 1; m++)
{
//每一轮开始时 默认没有进行过交换
isSort = false;
for (int n = 0; n < arr.Length - 1 - m; n++)
{
//如果第n个数大于第n + 1个数 那么就要交换位置
//交换相邻元素位置
//中间商不赚差价
if (arr[n] > arr[n + 1])
{
isSort = true;
int temp = arr[n + 1];
arr[n + 1] = arr[n];
arr[n] = temp;
}
//当一轮结束过后 如果isSort为false 说明没有发生交换 说明已经有序了
}
if (!isSort)
{
break;
}
}
五、总结
//总结
//基本概念
//两两相邻 不停比较
//不停交换
//比较 m轮
//套路写法
//两层循环
//外层轮数
//内层比较
//两值比较
//满足交换
//如果优化
//1.比过不比
//2.加入bool