冒泡排序以及优化

  最近需要用到冒泡排序,所以翻出来研究一下。冒泡排序的基础其实就是元素交换,是一种极其简单的排序算法。

  话不多说,直接上代码:

 1 #include <stdio.h>
 2 void bubble_sort(int arr[], int len)
 3 {
 4     int i, j, temp;
 5     for(i = 0; i < len - 1; i++)
 6     {
 7         for(j = 0; j < len - 1; j++)
 8         {
 9             if(arr[j] > arr[j + 1])
10             {
11                 temp = arr[j];
12                 arr[j] = arr[j + 1];
13                 arr[j + 1] = temp;
14             }
15         }
16     }
17 }
18     
19 int main () 
20 {
21     int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
22     int len = (int)sizeof(arr)/sizeof(arr[0]);
23     int i;
24     bubble_sort(arr, len);
25     for(i = 0; i < len; i++)
26     {
27         printf("%d ",arr[i]);
28     }
29     return 0;
30 }

以上是基础版,下面来讲一下原理。

  首先初始化一个数组 arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70}  我们需要从小到大对数组元素进行排序,运用最简单的元素交换步骤,比较相邻两个元素的大小,比较后,数值较大的往后移动。由此,两两比较多次后(这是一趟排序),数值最大的元素移动到数组尾部。经过多趟排序之后,数组元素将从小到大排列。

  但是这样的排序并不是最优选择。因为按照以上的算法,即使后面的数据已经排序完成,还是每一趟都要遍历。以下是优化的算法:

 1 #include <stdio.h>
 2 void bubble_sort(int arr[], int len)
 3 {
 4     int i, j, temp;
 5     int swapped = 1;                       //设置交换的标志位
 6     for(i = 0; i < len - 1; i++)
 7     {
 8         swapped = 0;                       
 9         for(j = 0; j < len - 1 - i; j++)   //减少了需要遍历的次数
10         {
11             if(arr[j] > arr[j + 1])
12             {
13                 temp = arr[j];
14                 arr[j] = arr[j + 1];
15                 arr[j + 1] = temp;
16                 swapped = 1;                //如果有数据交换,表示序列还没有完成排序,继续进行循环
17             }
18         }
19         if(swapped == 0)                    //如果没有元素交换,表示序列是顺序状态,退出循环
20         {
21             j = len - 1;
22         }
23     }
24 }
25 int main () 
26 {
27     int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
28     int len = (int)sizeof(arr)/sizeof(*arr);
29     int i;
30     bubble_sort(arr, len);
31     for(i = 0; i < len; i++)
32     {
33         printf("%d ",arr[i]);
34     }
35     return 0;
36 }

 

当然,冒泡排序还有更优化的方法:鸡尾酒排序,这种方法特点是在排序的过程中是双向进行的。程序如下:

 1 #include <stdio.h>
 2 
 3 void CockTailSort(int arr[], int len);
 4 void swap(int *a, int *b);
 5 
 6 int main () 
 7 {
 8     int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
 9     int len = (int)sizeof(arr)/sizeof(*arr);
10     int i;
11     CockTailSort(arr, len);
12     for(i = 0; i < len - 1; i++)
13     {
14         printf("%d ",arr[i]);
15     }
16     return 0;
17 }
18 
19 void swap(int *a, int *b)   //交换两元素的值  
20 {  
21     int t;  
22     t=*a;  
23     *a=*b;  
24     *b=t;  
25 }  
26   
27 void CockTailSort(int arr[], int len)
28 {
29     int i, left = 0, right = len - 1;
30     int swapped = 1;
31     while(swapped)
32     {
33         swapped = 0;
34         for(i = left; i < right; i++)       //向右排序,确认最大元素
35         {
36             if(arr[i] > arr[i+1])
37             {
38                 swap(&arr[i], &arr[i+1]);
39                 swapped = 1;
40             }
41         }
42         right--;                            
43         for(i = right; i > left; i--)       //向左排序,确认最小元素
44         {
45             if(arr[i] < arr[i-1])
46             {
47                 swap(&arr[i], &arr[i-1]);
48                 swapped = 1;
49             }
50         }
51         left++;
52     }
53 }

下图是排序的模式,更直观一点:

 

 冒泡排序,最好的情况是序列已经是正序,时间复杂度为O(n),最坏的当然是逆序,时间复杂度为O(n^2),另外冒泡排序需要一个空间作为数据交换的临时存储单元,因此空间复杂度为O(1)。

 

posted @ 2020-08-04 14:26  佳木  阅读(177)  评论(0编辑  收藏  举报