1.冒泡排序
1.1冒泡排序的原理
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序。
此时 有序空间在后面。
1.2冒泡排序的实现
import java.util.Arrays;
public class Sort {
public static void bubbleSort(int [] arr){
for(int bound=arr.length-1;bound>=0;bound--){
for(int cur=0;cur<bound;cur++){
if(arr[cur]>arr[cur+1]){
swap(arr,cur,cur+1);
}
}
}
}
public static void swap(int [] arr,int i,int j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
public static void main(String[] args) {
int [] arr={9,5,2,7,3,6,8};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}
2.快速排序
2.1快速排序的原理
快速排序的核心操作:partition
先在待排序空间选取一个“基准值”,然后把数组整理成左侧比基准值小,右侧比基准值(基准值可以取最后一个元素)大,使用左右下标两边往中间走来实现的。从左往右找一个比基准值大的元素,从右往左找一个比基准小的元素,然后交换两个元素的位置,继续往下走,进行交换两个元素,继续往下走,发现left和right重合了,此时发现重合元素的左边比基准值小,重合元素的右边比基准值大。
然后发现基准值左侧的值比基准值小,基准值右侧的值比基准值大。然后递归处理左右区间。
2.2快速排序的实现(递归)
import java.util.Arrays;
public class Sort {
public static void quickSort(int [] arr){
//构造一个辅助递归的方法
//在这个方法中明确指出争对哪个区间
//[0,length-1]
_quickSort(arr,0,arr.length-1);
}
public static void _quickSort(int [] arr,int left,int right){
if(left>=right){
//如果当前的空间为空,或只有一个元素
//都不需要处理
return;
}
//现针对当前的[left,right]进行partition
//方法的返回值,表示整理完当前的区间后,基准值所在的位置
//遍历过程中left和right重合的位置
int index=partition(arr,left,right);
//递归的对左侧区间进行快速排序
_quickSort(arr,left,index-1);
//递归的对右侧区间进行快排序
_quickSort(arr,index+1,right);
}
public static int partition(int [] arr,int left,int right){
//选取最右侧元素作为基准值
int v=arr[right];
int l=left;
int r=right;
//若果l和r重合,说明遍历完成
while(l<r){
//先从左往右,找一个比基准值大的数字
while(l<r&&arr[l]<v){
l++;
}
//当循环结束了之后,l就指向了比基准值大的元素
//从右往左找比基准值小的数字
while(l<r&&arr[r]>=v){
r--;
}
swap(arr,l,r);
}
//当l和r重合的时候,重合位置的元素
//就把重合位置的元素基准值位置的元素交换位置
swap(arr,l,right);
//最后返回重合的位置
return l;
}
public static void swap(int [] arr,int i,int j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
public static void main(String[] args) {
int [] arr={9,5,2,7,3,6,8};
quickSort(arr);
System.out.println(Arrays.toString(arr));
}
}
注意:
如果选取了最后一个位置作为基准值,必须先从左往右,再从右往左;如果选取了第一个元素作为基准值,则先从右往左,再从左往右。
快速排序的优化手段:
1)三数取中;
2)当待处理区间比较小的时候,就不继续递归了,直接针对该区域进行插入排序;
3)当递归达到一定的深度,并且当前的待处理区间比较大,还可以使用堆排序。
2.3快速排序的实现(非递归)
public static void quickSortByLoop(int [] arr){
//1.先创建一个栈,这个栈用来处理每一个待处理区间
Stack<Integer> stack=new Stack<>();
//2.把根节点入栈
stack.push(0);
stack.push(arr.length-1);
//循环取栈顶元素
while(!stack.isEmpty()){
//取得元素就是当前待处理空间
//取得顺序正好与插入的顺序相反
int right=stack.pop();
int left=stack.pop();
if(left>=right){
//如果是空区间或者只有一个元素,不需要排序
continue;
}
//调用partition方法调整当前区间
int index=partition(arr,left,right);
//右侧区间:[index+1,right]
stack.push(index+1);
stack.push(right);
//左侧区间:[left,index-1]
stack.push(left);
stack.push(index-1);
}
}
public static int partition(int [] arr,int left,int right){
//选取最右侧元素作为基准值
int v=arr[right];
int l=left;
int r=right;
//若果l和r重合,说明遍历完成
while(l<r){
//先从左往右,找一个比基准值大的数字
while(l<r&&arr[l]<v){
l++;
}
//当循环结束了之后,l就指向了比基准值大的元素
//从右往左找比基准值小的数字
while(l<r&&arr[r]>=v){
r--;
}
swap(arr,l,r);
}
//当l和r重合的时候,重合位置的元素
//就把重合位置的元素基准值位置的元素交换位置
swap(arr,l,right);
//最后返回重合的位置
return l;
}
public static void swap(int [] arr,int i,int j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
public static void main(String[] args) {
int [] arr={9,5,2,7,3,6,8};
quickSortByLoop(arr);
System.out.println(Arrays.toString(arr));
}
}