冒泡排序是选择排序中最为简单的一种,也是最为基础的一种。
他的规则是将第一个元素与第二个比较,比较后移动元素,再用第二个与第三个比较,直至最后一个元素,这是完成一趟排序,将最大的元素排到了最后。依此进行第二趟,第三趟直至排序完成。
先看下实际例子:
一般情况:
i值 原序列:10 3 7 8 5 2 1 4 9 6 交换范围
1 第1遍: 3 7 8 5 2 1 4 9 6 10 [0—10-1)
2 第2遍: 3 7 5 2 1 4 8 6 9 10 [0—10-2)
3 第3遍: 3 5 2 1 4 7 6 8 9 10 [0—10-3)
4 第4遍: 3 2 1 4 5 6 7 8 9 10 [0—10-4)
5 第5遍: 2 1 3 4 5 6 7 8 9 10 [0—10-5)
6 第6遍: 1 2 3 4 5 6 7 8 9 10 [0—10-6)
7 第7遍: 1 2 3 4 5 6 7 8 9 10 [0—10-7)
8 第8遍: 2 1 3 4 5 6 7 8 9 10 [0—10-8)
9 第9遍: 1 2 3 4 5 6 7 8 9 10 [0—10-9)
那普通的冒泡排序就是如下这种写法
#include <iostream> typedef int ElemType; void BubbleSort(ElemType *arr,int length); int main() { using namespace std; std::cout << "BubbleSort!" << std::endl; ElemType arr[] = {90,80,70,60,30,20,10}; int length = sizeof(arr)/ sizeof(arr[0]); BubbleSort(arr,length); for (int i = 0; i < length; ++i) { cout<<"The "<<i+1<<"th element is "<<arr[i]<<endl; } return 0; } void BubbleSort(ElemType *arr,int length){ ElemType temp; for (int i = 1; i < length ; ++i) {//进行n-1趟排序 for (int j = 0; j < length-i; ++j) {//在前n-i个未完成的排序中进行比较和元素移动 if(arr[j] > arr[j+1]){//交换 temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
时间复杂度:最好情况若表中的元素已经符合正向排序,那么只需比较n-1次即可排序完成,但是程序并不知道这已经完成了,于是会继续执行,那么执行次数为n-1+n(n-1)/2+交换次数,最好情况交换次数为0,最坏为3*n(n-1)/2,最终拟合时间复杂度为O(n^2)
那么对于已经基本有序的表能否更快一点呢?意思是让系统知道这个表已经排完序的时候,不用每次都执行完浪费时间呢?
我想唯一能让计算机知道这一点的就是用计算机的语言去告知他,就是设置标志位。
我的构想是,若在交换的内外设置标志位,标志不同的状态,每次只要进入了if语句,改变了元素,证明这次就没有排序完成;若没有进入if语句,那么就意味着其实已经完成排序可以不用继续进行下去了。
代码如下:
#include <iostream> #include <curses.h> typedef int ElemType; void BubbleSort(ElemType *arr,int length); int main() { using namespace std; std::cout << "BubbleSort!" << std::endl; ElemType arr[] = {90,80,70,60,30,20,10}; int length = sizeof(arr)/ sizeof(arr[0]); BubbleSort(arr,length); for (int i = 0; i < length; ++i) { cout<<"The "<<i+1<<"th element is "<<arr[i]<<endl; } return 0; } void BubbleSort(ElemType *arr,int length){ ElemType temp; bool CHANGE = true;//初始化为true for (int i = 1; i < length && CHANGE ; ++i) {//进行n-1趟排序,判断条件为true CHANGE = FALSE;//外部判断先为false for (int j = 0; j < length-i; ++j) {//在前n-i个未完成的排序中进行比较和元素移动 if(arr[j] > arr[j+1]){//交换 temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; CHANGE = true;//如果还有元素进行交换,那么就置为true } } } }
对于最坏的情况,冒泡排序当然无力改变时间复杂度,但对于最好的情况或是已经基本有序的数列,可以有效缩短时间。拿最好情况来比较,假设数列已经简单有序,则只需比较n-1次就结束函数了,无需再进行后面的操作。