冒泡排序
-
冒泡排序(Bubble Sort):它重复的走访过要排序的数列,每次比较两个元素,如果他们的顺序错误就将这两个数交换过来。走访数列的工作是重复的进行直到没有再需要交换,也就是排序已经完成。外层循环是因为总共要比较
len
次,内层循环是每次比较len-i
次,下标从0开始所以值范围限制到len-1-i
。算法名字“冒泡”的由来就是越小的元素会因为交换而慢慢的“浮”到数列的顶端。就是这个图啦~
每回比较都得到一个最大值,因此内循环的限制条件应该是j<len-1-i;
,因为每次循环都能得到一个最大值,因此循环到第i次会得到了i个最大值已经是被排好顺序的。
-
啥时最快:数组已经是正序了;啥时最慢:数组是反序时。
-
冒泡排序的性能:
时间复杂度:冒泡排序一共要进行(n-1)次循环,每一次循环都要与当前n-1次比较。所以一共的比较次数是:(n-1) + (n-2) + (n-3) + … + 1 = n*(n-1)/2,所以冒泡排序的时间复杂度是 O(n^2)。
空间复杂度:空间复杂度我们主要看额外利用的空间,比如我们在冒泡的过程中,涉及到数据交换,交换时需要申请临时的空间,它是常量级别的,其他不需开辟要额外的内存空间,所以空间复杂度为 O(1)。
C代码:
void bubbleSort(int arr[], int len)
{
int temp=0;
for(int i=0;i<len-1;i++)//总共要排序len次
{
for(int j=0;j<len-1-i;j++)//每回比较都得到一个最大值,因此这个限制条件应该是j<len-1-i;
{
if(arr[j]>arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
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
- 冒泡排序的升级版(冒泡的优化)
立一个flag,在第一趟序列遍历中没有元素发生交换则证明该序列已经有序,直接break跳出来就行。
/**
* 边界条件:
* 1) 判断数组是否有数据
* 算法思路:
* 1)外循环 for 需要 n-1 个数据 n-1 次冒泡
* 2)内循环每次冒泡的比较次数,每冒泡比较次数都 -1
* 3)冒泡优化
*/
void bubbleSort(int arr[], int len)
{
int temp=0;
for(int i=0;i<len-1;i++)
{
int flag=0;
for(int j=0;j<len-1-i;j++)
{
if(arr[j]>arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag=1;
}
}
if(flag==0)//若第一趟发现原数组没有需要交换的,证明是有序的,之后的几趟排序就不需要了
break;
}
}
- 还有一种:
第一层循环与i的初始值无关,而只与循环了多少次有关。第一层循环含义为:需要遍历arr.length-1次数组,才能将数组排好序;
第二层循环要解决的问题便是:待排序区域的起始和结尾位置,考虑在进行这个循环时,数组已经排好了几个值。
所以,以下方法也是可以的,还是要循环len次,依然是每次将最大值放到右边下次就不用在比较了。
C++代码:
void bubbleSort(int arr[], int len)
{
int temp = 0;
for(int i=len-1;i>0;i--)
{
for(int j=0;j<i;j++)
{
if(arr[j]>arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
python代码:
def bubbleSort(arr):
for i in range(len(arr)-1, 0, -1):
for j in range(0, i):
if arr[j]>arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr