文章目录
- 交换排序
- 一.冒泡排序
- 二.快速排序
- 1.挖坑法
- 2.Hoare法
交换排序
- 根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置
- 将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
一.冒泡排序
/**
* 冒泡排序
* 时间复杂度 n^2
* 空间复杂度 1
* @param array
*/
public static void bubbleSort(int[]array){
for (int i = 0; i < array.length-1; i++) {//趟数
boolean flg =false;
for (int j = 0; j < array.length-1-i; j++) {
if (array[j]>array[j+1]){
swap(array,j,j+1);
flg = true;
}
}
if (flg == false){
return;
}
}
}
1.遍历 i 代表交换的趟数,遍历 j 进行两两交换
2.j < array.length-1-i 是对于趟数的优化,每走一趟,交换就少一次
3.boolean flg =false;当两两交换时,flg变为true
4.进一步优化:如果遍历完,没发生交换,flg还是false,直接返回,排序结束
- 时间复杂度:O ( N2 )
- 空间复杂度:O ( 1 )
- 稳定性:稳定
二.快速排序
-
二叉树结构的交换排序方法
-
任取一个待排序元素作为基准值,把序列一分为二,左子序都比基准值小,右子序都比基准值大,左右两边再重复进行
- 左边找比基准值大的,右边找比基准值小的
1.挖坑法
- 基准值位置挖一个坑,后面找一个比基准值小的把坑埋上
- 前面找一个比基准值大的,埋后面的坑
- 当l==r时,把基准值填入剩下的坑中
- 左右两边重复进行上述步骤,直到排完为止
- 左右两边都以同样的方法进行划分,运用递归来实现
/**
* 快速排序 ---挖坑法
*
* @param array
*/
public static void quickSort(int[] array) {
quick(array, 0, array.length - 1);
}
private static void quick(int[] array, int start, int end) {
if (start >= end) {
return;//结束条件
// start == end,说明只剩一个了,是有序的,返回
//start > end ,说明此时的基准值在开头或者末尾
//在开头:start不变,end=pivot-1,start > end ,end=-1 没有左树
//在结尾:end不变,start = pivot+1,start > end,超出索引,没有右树
}
//不断递归quick
int pivot = partition(array, start, end);// 进行排序,划分找到pivot
//然后递归划分法左边,递归划分的右边
quick(array, start, pivot - 1);
quick(array, pivot + 1, end);
}
//划分,返回基准值
private static int partition(int[] array, int left, int right) {
int tmp = array[left];//挖一个坑,取left位置为基准值
while (left < right) {
//在右边找一个比基准值小的把坑填上
while (left < right && array[right] >= tmp) {//防止越界
right--;
}
array[left] = array[right];//找到比tmp小的数,填坑,
//在左边找一个比tmp大的值,填到右边的坑
while (left < right && array[left] <= tmp) {//防止越界
left++;
}
array[right] = array[left];
}//如果相遇了,退出循环
array[left] = tmp;//填坑
return left;
}
-
先划分序列,递归左边,然后再递归右边
-
递归结束条件:
start == end时,说明只剩一个了,是有序的,返回
start > end 时 ,说明此时的基准值在开头或者末尾如果基准值在开头:start不变,end=pivot-1,start > end ,end=-1 没有左树
如果基准值在结尾:end不变,start = pivot+1,start > end,超出索引,没有右树
2.Hoare法
- 不同的方法,找出基准值,排的序列是不一样的
- i记录基准值一开始在left位置的下标
- r找到比基准值小的停下来,l找到比基准值大的停下来,互相交换
- l和r相遇的时候,把i 记录基准值的初始下标和相遇位置交换
以左边为基准,先找右边再找左边,相遇的位置就是以右边为基准的值,要比基准小,才能交换
/**
* Hoare法 划分排序找基准值
* @param array
* @param left
* @param right
* @return
*/
private static int partition2(int[] array, int left, int right) {
int tmp = array[left];
int i = left;//记录基准值一开始在left位置的下标
while (left < right) {
while (left < right && array[right] >= tmp) {
right--;
}
while (left < right && array[left] <= tmp) {
left++;
}
swap(array,left,right);
}
swap(array,i,left);
return left;
}
点击移步博客主页,欢迎光临~