一:什么是冒泡排序
1、定义:
冒泡排序(Bubble Sort)是一种简单直观的排序算法,它通过依次比较相邻两个元素的大小,在每一次的比较的过程中,通过交换来达到有序的目的。
就像碳酸饮料中的气泡一样,从底部一直冒泡到顶部。
2、原理:
- 比较相邻的元素,如果第一个比第二个大或小,就交换它们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,最后的元素会是最大或者最小的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
3、动态图演示:
4、C# 代码实现:
namespace AlgorithmTest
{
class Program
{
static void Main(string[] args)
{
// 定义一个长度为5的数组
int[] array = new[]{ 5, 4, 2, 3, 8 };
BubbleSort(array);
Console.ReadKey();
}
static void BubbleSort(int[] array)
{
// 临时变量,用来接收两元素中较大或者较小的元素
int temp = 0;
// 外循环控制轮数
for (int i = 0; i < array.Length - 1; i++)
{
// 内循环两两元素比较
for (int j = 0; j < array.Length - 1 - i; j++)
{
// 从左往右,依次递增
if (array[j] > array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
// 通过循环打印结果
foreach (var item in array)
{
Console.Write(item + " ");
}
}
}
}
控制台输出结果如下所示
冒泡排序通过两次 for循环 实现,内循环进行两两元素之间的比较,而外循环决定将进行几次这样的内循环,才能彻底将所有元素比较一遍,完成冒泡排序。
二:冒泡排序的优化
1、分析:
冒泡排序有一个最大的问题就是这种算法不管有序还是没序,先执行循环再说。
举个数组例子:[ 1,2,3,4,5 , 6],很明显,这是一个有序的数组,根本不需要排序,如果你用了冒泡排序,它仍会双层循环一个不少的把数据遍历一遍,这是没必要做的事情,属于浪费资源。
针对这个问题,我们可以设定一个临时布尔值变量,来标记该数组是否已经有序,如果有序了就不用遍历了。
2、C# 代码:
为了更直观的做优化前后执行轮数的对比,我定义了一个 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 11 } 的数组,代码如下
namespace AlgorithmTest
{
class Program
{
static void Main(string[] args)
{
// 定义一个长度为12的数组
int[] array = new[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 11 };
BubbleSort(array);
Console.ReadKey();
}
static void BubbleSort(int[] array)
{
int temp = 0; // 临时变量,用来接收两元素中较大或者较小的元素
int flag = 0; // 仅用来记录循环轮数
// 外循环控制轮数
for (int i = 0; i < array.Length - 1; i++)
{
bool isSort = true;
// 内循环两两元素比较
for (int j = 0; j < array.Length - 1 - i; j++)
{
// 从左往右,依次递增
if (array[j] > array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
isSort = false;
}
}
if (isSort)
{
break;
}
else
{
flag++;
}
}
// 通过循环打印结果
foreach (var item in array)
{
Console.Write(item + " ");
}
Console.WriteLine("总共循环了 " + flag + " 轮");
}
}
}
我们知道,优化前执行的轮数 = 数组的长度 - 1 = 12 - 1 = 11 ,那优化后需要执行多少轮呢 ?如下所示
冒泡排序优化后的效果还是显而易见的。
虽然这样的优化对现在的计算机而言,也许并没有提高多大的效能,但更多的是我们对于算法思维的提高。
扩展:
一:冒泡排序什么时候最快 ? 答:当数据是正序时,时间复杂度 O(n)
二:冒泡排序什么时候最慢 ? 答:当数据是反序时,时间复杂度 O(n²)
三:多种编程语言实现冒泡排序(参考)
1:Java
public class BubbleSort implements IArraySort
{
@Override
public int[] sort(int[] sourceArray) throws Exception
{
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
for (int i = 1; i < arr.length; i++)
{
// 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
boolean flag = true;
for (int j = 0; j < arr.length - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = false;
}
}
if (flag)
{
break;
}
}
return arr;
}
}
2:JavaScript
function bubbleSort(arr)
{
var len = arr.length;
for (var i = 0; i < len - 1; i++)
{
for (var j = 0; j < len - 1 - i; j++)
{
// 相邻元素两两对比
if (arr[j] > arr[j+1])
{
// 元素交换
var temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
3:Python
def bubbleSort(arr):
for i in range(1, len(arr)):
for j in range(0, len(arr)-i):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
4:PHP
function bubbleSort($arr)
{
$len = count($arr);
for ($i = 0; $i < $len - 1; $i++)
{
for ($j = 0; $j < $len - 1 - $i; $j++)
{
if ($arr[$j] > $arr[$j+1])
{
$tmp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1] = $tmp;
}
}
}
return $arr;
}
5:GO
func bubbleSort(arr []int) []int
{
length := len(arr)
for i := 0; i < length; i++
{
for j := 0; j < length-1-i; j++
{
if arr[j] > arr[j+1]
{
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
return arr
}
6:C++
void swap(int *a, int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
void buddle_sort(int *a,int len)
{
int max = len-1;
int i,j;
for (int i = 0; i < max; i++)
{
for (int j = 0; j < max-i; j++)
{
if (a[j+1] < a[j])
{
swap(a,j,j+1);
}
}
}
}
声明:
一:博文中用到的动态效果图,录取自 vx 公众号《五分钟学算法》以及《程序员小灰》,对算法感兴趣的可以关注下。
二:文章思路开源项目地址,整理人 hustcc
如果这篇博客有幸帮到了您,欢迎点击下方链接,和更多志同道合的伙伴一起交流,一起进步。
结束语