标签:
冒泡排序基本思想:两两比较相邻记录的关键字,如果反序就交换,直到没有反序为止。
1 #define MAXSIZE 10 2 3 typedef struct 4 { 5 int r[MAXSIZE]; //r[0] 用作哨兵或临时变量 6 int length; //记录顺序表的长度 7 }SqList; 8 9 void swap(SqList *L, int i, int j) 10 { 11 int temp = L->r[i]; 12 L->r[i] = L->r[j]; 13 L->r[j] = temp; 14 }
思路是让每一个关键字都和它后面的每一个关键字作比较,如果大就交换。严格来说并不是标准的冒泡排序算法,它并不满足“两两比较相邻记录”的冒泡排序思想。
1 void BUbbleSort(SqList * L) 2 { 3 int i, j; 4 for (i=1; i<L->length; i++) //注意迭代范围 5 { 6 for (j=i+1; j<=L->length; j++) //注意迭代范围 7 { 8 if (L->r[i] > L->r[j]) 9 { 10 swap(L, i, j); 11 } 12 } 13 } 14 }
通过从后面两两相邻的比较,较小的数字如同气泡一样慢慢地浮到上面,因此为冒泡算法。
1 void BubbleSort(SqList * L) 2 { 3 int i, j; 4 for (i=1; i<L->length; i++) 5 { 6 for (j=L->length-1; j>=i; j--) //j是从后往前循环 7 { 8 if (L->r[j] > L->[j+1]) //条件:前者大于后者 9 { 10 swap(L, j, j+1); 11 } 12 } 13 } 14 15 }
但是它的缺点在于当后面一部分的数字有序时,如{2,1,3,4,5,6,7,8,9}
当经过第一轮比较后(外层循环,即 i = 1),交换了2和1,此时序列就有序了,但算法还是会将 i =2到9以及每个循环中的 j 都执行一遍,尽管没有交换数据,但是之后的大量比较还是大大冗余。
代码改动的关键在于i 变量的for 循环中,增加了对 flag是否为true的判断,经过这样的改进,冒泡排序在性能上就有了一些提升,可以避免在已经有序的情况下的无意义的循环判断。
1 void BubbleSort(SqList * L) 2 { 3 int i, j; 4 Status flag = TRUE; 5 for (i=1; i<L->length && flag; i++) //若flag为false就退出循环 6 { 7 flag = FALSE; //初始化为flase 8 9 for (j=L->length-1; j>=i; j--) 10 { 11 if (L-r[j] > L->r[j+1]) 12 { 13 swap(L, j, j+1); 14 flag = TRUE; //如果有数据交换,flag 就为true 15 } 16 } 17 } 18 }
最好的情况:即表本身就是有序的,根据改进的代码,为n-1次比较,没有数据交换,所以时间复杂度为 O(n).
最坏的情况:即表是逆序的,需要比较 ∑1n-1 (n-i) = n-1 + n-2 + ... + 1 = n(n-1)/2 次,并作等数量级的记录移动。
因此总的时间复杂度为O(n2).
标签:
原文地址:http://www.cnblogs.com/shiddong/p/4449976.html