简介
交换排序是一种通过不断比较数组中两个元素的大小,如果大小顺序与要得到的排序相反,则交换位置,否则不交换的排序方法。常用的交换排序法就是冒泡排序和快速排序。
一、交换排序
假设有n个元素,则第一趟排序中,依次比较下标为0与1、1与2、2与3……n-1与n的大小,并且每次比较中,如果与目标顺序不同,则交换两个数的大小。第二趟排序中,依次比较下标为0与1、1与2、2与3……n-2与n-1的大小……一共n-1趟。
举例
注:下面的数组按升序排序
第n趟冒泡排序 | 数组元素 | 执行的操作 |
---|---|---|
0 | 39 , 80 , 76 , 41 , 13 | 无 |
1 | 39 , 80 , 76 , 41 , 13 | 比较39和80的大小 |
1 | 39 , 76 , 80 , 41 , 13 | 比较80和76的大小并交换位置 |
1 | 39 , 76 , 41 , 80 , 13 | 比较80和41的大小并交换位置 |
1 | 39 , 76 , 41 , 13 , 80 | 比较80和13的大小并交换位置 |
2 | 39 , 76 , 41 , 13 , 80 | 比较39和76的大小 |
2 | 39 , 41 , 76 , 13 , 80 | 比较76和41的大小并交换位置 |
2 | 39 , 41 , 13 , 76 , 80 | 比较76和13的大小并交换位置 |
2 | 39 , 41 , 13 , 76 , 80 | 比较76和80的大小 |
3 | 39 , 41 , 13 , 76 , 80 | 比较39和41的大小 |
3 | 39 , 13 , 41 , 76 , 80 | 比较41和13的大小并交换位置 |
3 | 13 , 39 , 41 , 76 , 80 | 比较39和13的大小并交换位置 |
至此,排序完成,最后的序列为[13 , 39 , 41 , 76 , 80]
特点
显然,冒泡排序是一种O(n2)的算法,而且它是稳定的
二、快速排序
冒泡排序虽然稳定,但是时间复杂度太高了,所以在对速度要求较高的情况下,我们更倾向于使用另一种算法——快速排序算法。
快排的基本思想是(默认升序),将数组的第一个元素作为关键码Key,并定义2个变量i、j,分别指向数组起始和末尾下标,每一趟排序,从j开始往前扫描找出第一个比Key小的元素,然后交换nums[i]和nums[j],然后从i往后扫描找出第一个比Key大的元素,交换nums[i]和nums[j]。直到i== j时跳出循环。
举例
数组太大了着不住啊~所以就用长度小一点数组举例啦。。。
键值Key = 39
第n趟快速排序 | 数组元素 | i | j | 执行的操作 |
---|---|---|---|---|
0 | 39 , 80 , 4 , 5 | 0 | 3 | 无 |
1 | 5 , 80 , 4 , 39 | 0 | 3 | 从后往前找出比Key小的数,然后交换nums[i]、nums[j] |
1 | 5 , 39 , 4 , 80 | 1 | 3 | 从前往后找出比Key大的数,然后交换nums[i]、nums[j] |
2 | 5 , 4 , 39 , 80 | 1 | 2 | 从后往前找出比Key小的数,然后交换nums[i]、nums[j] |
2 | 5 , 4 , 39 , 80 | 2 | 2 | 从前往后找出比Key大的数,然后交换nums[i]、nums[j] |
可见,经过快速排序后,确实将比Key小的值划分到了前面,比Key大的值划分到了后面。然后我们再分别将(start, i -1)和(i+1, end)之间的数组调用快速排序,就能得到结果了
第n趟快速排序 | 数组元素 | i | j | 执行的操作 |
---|---|---|---|---|
3 | 4 , 5 , 39 , 80 | 0 | 1 | 从后往前找出比Key小的数,然后交换nums[i]、nums[j] |
3 | 4 , 5 , 39 , 80 | 1 | 1 | 从前往后找出比Key大的数,然后交换nums[i]、nums[j] |
所以,最后的结果是[4 , 5 , 39 , 80]
特点
最优情况下,快排的时间复杂度是O(nlog2n),一般情况也是O(nlog2n),但是最坏的情况是当数组完全有序时,时间复杂度为O(n2n),而且快排是一种不稳定的算法。然而由于快排确实足够快,所以在对稳定性要求不高的时候,可以使用快排。
附代码:
1.冒泡排序
class BubbleSortTool{
public static void bubbleSort(int[] nums){
int swap ;//每趟的交换次数
int temp ;
//需要n-1趟交换
for(int i = 0; i < nums.length -1; i ++){
swap = 0;
for(int j = 1; j < nums.length; j ++){
if(nums[j] < nums[j-1]){
temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
++swap;
}
}
if(swap == 0)//如果该趟没有交换,则表明数组已经是有序的了
break;
}
}
}
2.快速排序
class QuickSortTool{
public static void quickSort(int[] nums ,int start , int end){
if(start >= end)
return ;
int i = start , j = end;
int key = nums[start];
int temp;
while(i < j){
// System.out.println("sort");
for(; i < j ; j --){
if(key > nums[j]){
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
break;
}
}
for(; i < j ; i ++){
if(nums[i] > key){
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
break;
}
}
}
quickSort(nums,start,i-1);
quickSort(nums,i+1,end);
}
}