---恢复内容开始---
冒泡排序:
一般冒泡排序我们都很容易想到以下的方法,但事实上冒泡排序还有一些地方可以改进。最主要的方法是引入标志位。
void print(int *p, int length) {
for (int i = 0; i < length; i++) {
cout << p[i] << ",";
}
}
void BubbleSort(int *p, int length) {
for (int i = 0; i < length; i++) {
for (int j = 0 ; j < length-i-1; j++) {
if (p[j]>p[j+1]) {
swap(p[j], p[j+1]);
}
}
}
print(p,length)
}
int main()
{
int arr[7] = {2,4,5,1,7,3,6};
int length = sizeof(arr) / sizeof(int);
BubbleSort(arr,length);
return 0;
}
(最后一行是输出的结果)
改进方案一
看到上面运行结果,第4,5,6,7趟都是没有发生逆序对的互换,但算法还是依旧进行了比较。
为此,引入一个排序标志。
void BubbleSort(int *p, int length) {
for (int i = 0; i < length; i++) {
bool sorted = true;
for (int j = 0 ; j < length-i-1; j++) {
if (p[j]>p[j+1]) {
swap(p[j], p[j+1]);
sorted = false; //如果有逆序对,说明还没有排好序
}
}
if (sorted) { //没有逆序对,说明已经排好序了,可以直接输出。
break;
}
}
print(p,length);
}
(最后一行是输出的结果)
由此可见,到第4趟发现没有逆序对了,就会停止。
假设这段有序的区间是[0,n1/2),那么按照这个算法算出来的复杂度就是 O(n2/3) ,即 n*n1/2
改进方案二(比方案一更优化)
由方案一我们得到启发,如果我们能够对已经排好序的部分不再去比较的话,那么性能会更好。例如
假设int arr[12] = {2,4,5,1,7,3,6,8,9,10,11,12};
如果我们得到6的位置的话,那么6之后的我们就不去比较了。
那6这个位置怎么得到呢?
我们可以设置一个变量,记录最后一次逆序对发生变化的位置。得到的就是排好序的部分里面排在最前的位置,也就是6的位置。
void BubbleSort(int *p, int length) {
int pos_temp = length - 1;
for (int i = 0; i < length; i++) {
int pos = pos_temp;
for (int j = 0 ; j < pos; j++) {
if (p[j]>p[j+1]) {
swap(p[j], p[j+1]);
pos_temp = j;//记录最后一次逆序对发生变化的位置
}
}
if (pos== pos_temp) {//如果没变过,说明没有逆序对了,可以直接输出
break;
}
}
print(p,length);
}
如上图,进行过一趟比较之后,我们就记录好了6的位置,也就是第6位。那么此后我们就不管6之后的数据了。