冒泡排序(Bubble Sort)是一种极其简单的排序算法。
它重复地走访过要排序的数列,依次比较相邻两个元素,如果他们的顺序错误就把他们调换过来,直到没有元素再需要交换,排序完成。
这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序算法的运作如下:
- 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
冒泡排序算法思路
冒泡排序的C语言代码如下:
- void vBubbleSort(int a[], int n){
- int i, j, temp;
- for (j = 0; j < n - 1; j++){ //每次最大元素就像气泡一样"浮"到数组的最后
- for (i = 0; i < n - 1 - j; i++){ //依次比较相邻的两个元素,使较大的那个向后移
- if(a[i] > a[i + 1]){
- temp = a[i];
- a[i] = a[i + 1];
- a[i + 1] = temp;
- }
- }
- }
冒泡排序算法
放几张图直观的了解下
对序列{ 6, 5, 3, 1, 8, 7, 2, 4 }进行冒泡排序
从上面的算法可以看出,没趟都要遍历比较,即使数据已经是排序好的,上面的第7趟完全可以不用排序的,因为第6趟的时候已经没有数据做交换了,对代码改进如下:
- void vBubbleSortChange(int a[], int n){
- int i,j,temp;
- int swapped = 1;
- for (j = 0; j < n - 1; j++){ //每次最大元素就像气泡一样"浮"到数组的最后
- swapped = 0;
- for (i = 0; i < n - 1 - j; i++){ //依次比较相邻的两个元素,使较大的那个向后移
- if(a[i] > a[i + 1]){ //交换两个数
- temp = a[i];
- a[i] = a[i + 1];
- a[i + 1] = temp;
- swapped = 1;
- }
- }
- if( swapped == 0) {j = n-1;}//如果没有元素交换,说明序列是顺序的,退出循环
- }
- }
冒泡排序算法改进
放一张直观些的图片,注意观察最后的几趟没有做遍历判断
冒泡排序改进
冒泡排序还有一种更好的改进排序的方法,叫鸡尾酒排序。
鸡尾酒排序也就是定向冒泡排序, 鸡尾酒搅拌排序, 搅拌排序 (也可以视作选择排序的一种变形), 涟漪排序, 来回排序 or 快乐小时排序, 是冒泡排序的一种变形。
此演算法与冒泡排序的不同处在于排序时是以双向在序列中进行排序。
C语言代码如下:
- void vCockTailSort(int arr[],int len){
- int tmp,i,left=0,right = len-1;
- while(left < right){
- for(i=left;i<right;i++){//正向冒泡,确定最大值
- if(arr[i]>arr[i+1]){
- tmp = arr[i];
- arr[i] = arr[i+1];
- arr[i+1] = tmp;
- }
- }
- right--;
- for(i=right;i>left;i--){//反向冒泡,确定最小值
- if(arr[i]<arr[i-1]){
- tmp = arr[i];
- arr[i] = arr[i-1];
- arr[i-1] = tmp;
- }
- }
- left++;
- }
- }
鸡尾酒排序
上面的代码比较直观的展现了鸡尾酒排序的过程,但是也可以做些优化,就是在正反向遍历的时候记录最后一次交换元素的位置作为左右限制的边界,改进代码如下:
- void vCockTailSortChange(int arr[],int len){
- int tmp,i,left=0,right = len-1;
- int swapped = 1;
- bound = 0;//记录某趟遍历的最后一次交换元素的位置,优化减少循环次数
- while(swapped){//如果没有元素交换,说明序列是顺序的
- swapped = 0;
- for(i=left;i<right;i++){//正向冒泡,确定最大值
- if(arr[i]>arr[i+1]){
- tmp = arr[i];
- arr[i] = arr[i+1];
- arr[i+1] = tmp;
- swapped = 1;
- bound = i;
- }
- }
- right=bound;//缩小遍历边界
- for(i=right;i>left;i--){//反向冒泡,确定最小值
- if(arr[i]<arr[i-1]){
- tmp = arr[i];
- arr[i] = arr[i-1];
- arr[i-1] = tmp;
- swapped = 1;
- bound = i;
- }
- }
- left=bound;//缩小遍历边界
- }
- }
鸡尾酒排序算法改进边界
放一张更加直观的图片,注意图片中边界的优化
鸡尾酒排序优化边界