基于冒泡排序的增强型算法
今天,闲来无事,用c语言来写一个排序算法。在写算法的时候,首先想到的就是最简单的排序算法-冒泡排序算法。算法很简单,几行代码就完成了。但在完成之后,从该算法本身考虑是否可以节省效率的实现呢?
首先看一下冒泡排序的最基础的代码实现。
void bubbleSort(char *name[], int n) {
char *tmp;
int i, j;
for (i = 0; i < n; i++) {
for (j = n - 1; j > i; j--) {
if (strcmp(name[j - 1], name[j]) > 0) {
tmp = name[j - 1];
name[j - 1] = name[j];
name[j] = tmp;
}
}
}
}
针对代码,首先分析了算法的实现的细节。该算法在实现过程中,如果中间的一次循环中,一次交换都没有发生,则进行下一个循环。而仔细分析,我们可以知道,如果在一次循环排序中,没有发生任何的元素的互换,则说明该排序数组已经排好序,那么,算法即算执行完毕。针对这种情况,我们是否可以对算法进行调优呢?
既然是考虑是否有元素互换,那么,我们可以在元素互换的操作中,增加标示来实现我们希望的这种想法。代码如下:
void bubbleSort(char *name[], int n) {
char *tmp;
int i, j;
for (i = 0; i < n; i++) {
int flag = 0;
for (j = n - 1; j > i; j--) {
if (strcmp(name[j - 1], name[j]) > 0) {
tmp = name[j - 1];
name[j - 1] = name[j];
name[j] = tmp;
flag = 1;
}
}
if (!flag) break;
}
}
在这里,我不去做太多数学上的分析,大家可以分析一下。
到这里,感觉该算法还是有缺陷。缺陷在哪里呢?冒泡排序中(假设是从小到大的排序),我们的目标是将小的放到最前面,大的放在最后面。而在冒泡算法中,只是单一的去做了小元素的查找和前移,而对于较大的数据,就不去理会。而在我们的算法中,没循环一次,都需要耗费一定的时间效率,而如果在每一次的循环中,除了将小的元素往前移,而同时找出剩下元素中最大的一个放在数组的后面去呢?这样,我们可以节省不少的时间开销,提升了算法的效率。
基于上面的想法,在循环中同时对小的数据往前排,而大的数据也找出来,将其排到后面。具体的算法描述:
1、从数组的最后一个元素(i)开始,比较其同前面的一个元素(i-1)的大小,如果最后一个元素要比其前面的一个元素小,则同前一个元素交换位置(用i表示元素的位置),并用一个标示来表示进行过排序。
2、同时,我们假定最后一个元素是最大的。并且,将该最大的元素做出标示,表示其目前是最大的元素(用k标示该最大元素的位置)。将该元素同位置为i的元素进行比较。因为在1步中,已经对元素进行了比较,可以知道,在i位置的元素一定大于i-1位置的元素。如果k位置的元素要小于i位置的元素,则进行交换,并用一个标示来表示进行过元素的交换。
3、一轮完成之后,最小的元素将会排到数组的最前面,而最大的元素排在最后面。所以,在进行下一轮的排序时,次小的元素的位置需要向后移位,而次大的元素位置需要向前移动一位。
4、当次小值的位置大于或等于次大值的位置时,退出排序。
上述的算法描述得不是非常清晰,根据上面的算法描述,提供具体的算法实现供参考:
void bubbleSort(char *name[], int n) {
char *tmp;
int i, j, k,cFlag;
int circle = 0;
cFlag = 0;
k = n - 1;
for (i = 0; i < n; i++) {
int flag = 0;
cFlag = 0;
for (j = k; j > i ; j--) {
if (strcmp(name[j - 1], name[j]) > 0) {
tmp = name[j - 1];
name[j - 1] = name[j];
name[j] = tmp;
flag = 1;
}
if (strcmp(name[j], name[k]) > 0) {
tmp = name[j];
name[j] = name[k];
name[k] = tmp;
cFlag = 1;
}
}
if(cFlag==1){
k = k-1;
}
if (!flag)
break;
}
}
经过上面的一个改造,对冒泡排序中所能做的改进也想不出更优的算法了。上面提出的这些算法,仅供参考。而对于改造算法的想法,只是出于对算法效率提升的角度来考虑,希望能够对现有算法的实现进行相应的调整和提高,以便可以得到更优的算法实现。同时,也是提醒自己,可以通过该示例,举一反三,为工作中所遇到的问题,多一些想法,就可以获得多一些解决途径。