交换排序是指在排序过程当中,经过待排序记录序列中元素间关键字的比较,将数据元素进行交换来达到排序目的的方法,主要包括冒泡排序和快速排序。git
源码:https://github.com/fangyz/myDataStructuregithub
/* 冒泡排序的基本思想是对全部相邻记录的关键字进行比较,若是a[j]>a[j+1]则将其交换,最终达到有序化。其处理步骤以下: (1)首先将整个待排序的记录分为有序区和无序区,初始状态有序区为空无序区则为整个待排序的记录。 (2)对无序区从前日后依次将相邻记录的关键字进行比较,若逆序则进行交换,从而使得较大的数据元素右移,这样最终造成有序序列。 经过上面的步骤能够发现,每一次冒泡排序都将无序区中最大的数据元素移到有序区的最右边。而且,对于含n个数据元素的数据序列,最多须要通过n-1趟冒泡排序。 */ void BubbleSort(int* a,int length) { if (a == NULL || length <= 0) return; int i, j,temp; for (i = length - 1; i > 0; i--){ for (j = 0; j <i; j++){ if (a[j]>a[j + 1]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } //若是一次循环中,没有进行数据交换,那么就说明序列已经有序。 void BetterBubbleSort(int* a, int length){ if (a == NULL || length <= 0) return; int i, j, temp; bool isChanged=false; for (i = length - 1; i > 0; i--){ isChanged = false; for (j = 0; j <i; j++){ if (a[j]>a[j + 1]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; isChanged = true; } } if (isChanged == false) break; } } //更好的冒泡排序 void BestBubbleSort(int *a, int length) { int i, j; int temp; bool isChange; int lastMove; if (a == NULL || length <= 0) return; for (i = length - 1; i>0; i--) { isChange = false; for (j = 0; j<i; j++) //一次执行将最大的数交换到最后面 { if (a[j + 1]<a[j]) { temp = a[j + 1]; a[j + 1] = a[j]; a[j] = temp; isChange = true; //优化点1:若是一次循环中没有数进行交换那说明已经有序了 lastMove = j; //优化点2:里面的for执行完毕后, 说明j到i之间的数据已经有序了,j之前的数据可能还不是有序的。 } } if (isChange == false) break; i = lastMove + 1;
} }
冒泡排序是一种稳定的排序方法,由于只有在大于后一个数的状况下才进行交换。冒泡排序最好状况比较次数为n-1,移动次数仅为0,此时数据元素自己就是有序序列。最坏状况下比较次数为n*(n-1)/2,移动次数为3n(n-1)/2,平均时间复杂度为O(n^2)。接下来是快速排序。数组
/* 快速排序,能够看到它的时间复杂度主要集中在外面的while循环,这个循环的做用是进行比较找到一个位置s将数组分为0~s和s~length,也就是说快速排序的时间复杂度集中在划分区域上。 在划分区域时,首先就算划分了区域,但仍是要对这一整个数组进行比较,比较的次数是一个n阶函数,接下来重点就是划分的次数了。 最好状况下若是每次都是划分的中间的区域,那么划分次数为lbn,最坏状况下若是每次划分有一个区域是空的,那将会划分n-1次,故时间复杂度最坏O(n^2),最好是O(lbn)。 至于为何平均时间复杂度为O(nlbn)课本上写了一大堆计算公式然而暂时并无看懂。。。。 */ void QuickSort(int *a, int start, int end) { if (a == NULL || start < 0 || (start>=end)) return; int s = start, e = end - 1; int index; int value = a[s]; while (s < e){ //必定要注意这个地方加=,由于若是不加的话,就是死循环了。 //这个地方还有一点要注意,那就是要加上s<e,由于条件是大于或等于,那么这时有可能e会小于s。 while (a[e]>=value&&s<e) e--; //如今执行到这个地方说明a[e]<value了,因此要让a[s]=a[e],a[e]=value,可是这里只对a[s]进行了赋值, //缘由是在循环中,让a[s]=a[e]后,接下来的while循环可以继续执行,当遇到a[s]>value时,此时进行替换的是a[e],即将大的数放到e这个地方。 //这样能够发现让a[s]=a[e]后就可让s向前增长,当s增长到a[s]>value时便让a[e]=a[s],这样下一次while循环中a[e]便大于value了额,e就能够向后减小了。 a[s] =a[e]; while (a[s] <= value&&s<e) s++; a[e] = a[s]; //咱们还能够发现每次执行到这个地方的时候,数组中有2个重复值, //那就是a[e]==a[s]>value,若是不知足s<e跳出循环那就要让a[s]=value。 } a[s] = value; if (s < end - 1) QuickSort(a, s + 1, end); if (s>start + 1) QuickSort(a, start, s); }