基本思想
遍历一个序列,对相邻的两个数比较排序,使小的上浮、大的下沉。
因为是自上而下遍历,因此最终得到的是最大的先沉到底部,较小的元素则一点一点的上浮。
这就是冒泡。
示例:
// 升序,左起
/*初始值*/ 12, 7, 1, 8, 5, 10, 6, 3, 9
/*第一趟*/ 7, 1, 8, 5, 10, 6, 3, 9, 12
/*第二趟*/ 1, 7, 5, 8, 6, 3, 9, 10,12
/*第三趟*/ 1, 5, 7, 6, 3, 8, 9, 10,12
/*第四趟*/ 1, 5, 6, 3, 7, 8, 9, 10,12
/*第五趟*/ 1, 5, 3, 6, 7, 8, 9, 10,12
/*第六趟*/ 1, 3, 5, 6, 7, 8, 9, 10,12
/*第七趟*/ 1, 3, 5, 6, 7, 8, 9, 10,12
/*第八趟*/ 1, 3, 5, 6, 7, 8, 9, 10,12
改进一:
如果一次遍历没有发生交换,说明已经排好了,可以提前结束
改进二:
最后一次交换位置的后面,都是排好了的,那么可以记录下最后一次排序位置,下次循环的哨兵可直接设置在此处。
改进三:
同时对最大、最小进行冒泡。即、一次冒泡中,先进行一轮正向冒泡,再进行一轮反向冒泡,同时设置首尾哨兵。
任意一轮没有交换,可提前结束。
每一轮都记录最后交换位置,下一回相反的冒泡直接从最后交换位置开始。
注意:这种排序是先将两端排好、再排中间,此时的循环不能以链表长度为准,而应该以 未排序的左、右索引值为准。
代码:
void printList(int *l, int n) {
for (int i = 0; i < n; i++) {
printf("%d ", l[i]);
}
printf("\n");
}
int main() {
int list[50] = { 12, 7, 1 , 8, 5, 10, 6, 3, 9 };
int n = 9;
printList(list, n);
// 升序,大的先排,小的向上冒泡
for ( int i = n - 1; i >= 0; ){
// 以 i 为哨兵,从 顶部 开始。
int lastIndex = 0;
bool hasSwap = false;
for (int j = 0; j < i; j++){
// 如果 j 比它后面的数大,那么就交换
if ( list[j] > list[j+1] ){
int k = list[j];
list[j] = list[j + 1];
list[j + 1] = k;
hasSwap = true;
lastIndex = j;
}
}
// 如果一次遍历没有发生交换,说明已经排好了,可以提前结束
if ( !hasSwap ){
break;
}
// 记录最后一次交换的 index,用来当做下一次循环的哨兵
i = lastIndex;
printList(list, n);
}
printList(list, n);
printf("==================\n");
// 升序,小的先排,大的向下沉
for (int i = 0; i < n;) {
// 以 i 为哨兵,从 底部 开始。
int lastIndex = i;
bool hasswap = false;
for (int j = n - 1; j > i; j--) {
// 如果 j 比它前面的数小,那么就交换
if (list[j] < list[j - 1]) {
int k = list[j];
list[j] = list[j - 1];
list[j - 1] = k;
hasswap = true;
lastIndex = j;
}
}
// 如果一次遍历没有发生交换,说明已经排好了,可以提前结束
if ( !hasswap ){
break;
}
i = lastIndex;
printList(list, n);
}
printList(list, n);
//printf("==================\n");
// 升序,双向冒泡,先从底部开始向上冒泡
int leftIndex = 0;
int rightIndex = n - 1;
while (leftIndex < rightIndex) {
int lastIndex = leftIndex;
bool hasSwap = false;
// 先向上冒泡一轮
for (int j = leftIndex; j < rightIndex; j++) {
if ( list[j] > list[j + 1] ){
int k = list[j];
list[j] = list[j + 1];
list[j + 1] = k;
hasSwap = true;
lastIndex = j;
}
}
// 提前结束
if ( !hasSwap ) {
break;
}
// 向上冒泡,更新的是下限
rightIndex = lastIndex;
printList(list, n);
printf("leftIndex:%d, rightIndex:%d\n", leftIndex, rightIndex);
// 再向下冒泡一轮
for (int j = rightIndex; j > leftIndex; j--) {
if (list[j] < list[j - 1] ) {
int k = list[j];
list[j] = list[j - 1];
list[j - 1] = k;
hasSwap = true;
lastIndex = j;
}
}
// 提前结束
if (!hasSwap) {
break;
}
// 向下冒泡,更新的是上限
leftIndex = lastIndex;
printList(list, n);
printf("leftIndex:%d, rightIndex:%d\n", leftIndex, rightIndex);
}
printList(list, n);
system("pause");
return 0;
}
以上
原文链接 http://blog.youkuaiyun.com/u011546766/article/details/74053481