最常用的:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。
当某次冒泡操作已经没有数据交换时,说明已经达到完全有序,不用再继续执行后续的冒泡操作
代码
/**
* @author: xuxu
* @date 2020/2/27 9:29
* @Description: 冒泡排序
*/
public class BubbleSort {
public static void bubbleSort(int[] arr){
//控制第几次排序
for(int i=0;iarr[j+1]){
int temp = arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
isSort=true;
}
}
if(!isSort){
System.out.print("第"+(i+1)+"次排序后数组无变化退出");
break;
}
//遍历
System.out.print("第"+(i+1)+"次排序后数组为:");
for (int k=0;k
首先,我们将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。
插入排序也包含两种操作,一种是元素的比较,一种是元素的移动。当我们需要将一个数据 a 插入到已排序区间时,需要拿 a 与已排序区间的元素依次比较大小,找到合适的插入位置。找到插入点之后,我们还需要将插入点之后的元素顺序往后移动一位,这样才能腾出位置给元素 a 插入。
/**
* @author: xuxu
* @date 2020/2/27 9:56
* @Description:插入排序
*/
public class InsertSort {
public static void insertSort(int[] arr){
//这里循环的是未排序部分
for(int i=1;i=0;j--){
//如果前一个数字大于要插入的数字则向后移动让出位置
if(arr[j]>insertNum){
arr[j+1] = arr[j];
}else{
//一旦他找到对的位置,则不需要向前继续找,因为前面是排好序的
break;
}
}
//将要插入的数放入前面找到的插入的位置 这里j+1是因为前面j--了
arr[j+1]=insertNum;
//遍历
System.out.print("第"+(i)+"次排序后数组为:");
for (int k=0;k
选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。
/**
* @author: xuxu
* @date 2020/2/27 11:02
* @Description: 选择排序
*/
public class SelectSort {
public static void selectSort(int[] arr){
for (int i=0;iarr[min+1]){
//先找出未排序区最小的一个下标
min = min+1;
}
}
//将min放入已排序区的最后面,同时原位置的元素放在min处
int temp = arr[i];
arr[i]=arr[min];
arr[min] = temp;
//遍历
System.out.print("第"+(i+1)+"次排序后数组为:");
for (int k=0;k
从推荐使用的角度看 插入>冒泡>选择
分治算法一般都是用递归来实现的。分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突。
递归公式
递推公式:
merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
终止条件:
p >= r 不用再继续分解
merge_sort(p…r) 表示,给下标从 p 到 r 之间的数组排序。我们将这个排序问题转化为了两个子问题,merge_sort(p…q) 和 merge_sort(q+1…r),其中下标 q 等于 p 和 r 的中间位置,也就是 (p+r)/2。当下标从 p 到 q 和从 q+1 到 r 这两个子数组都排好序之后,我们再将两个有序的子数组合并在一起,这样下标从 p 到 r 之间的数据就也排好序了
合并过程
我们申请一个临时数组 tmp,大小与 A[p…r] 相同。我们用两个游标 i 和 j,分别指向 A[p…q] 和 A[q+1…r] 的第一个元素。比较这两个元素 A[i] 和 A[j],如果 A[i]<=A[j],我们就把 A[i] 放入到临时数组 tmp,并且 i 后移一位,否则将 A[j] 放入到数组 tmp,j 后移一位。
继续上述比较过程,直到其中一个子数组中的所有数据都放入临时数组中,再把另一个数组中的数据依次加入到临时数组的末尾,这个时候,临时数组中存储的就是两个子数组合并之后的结果了。最后再把临时数组 tmp 中的数据拷贝到原数组 A[p…r] 中。
/**
* @author: xuxu
* @date 2020/2/27 14:32
* @Description: 归并排序
* f(a,p) =f(a,q)+f(q+1,p)
*/
public class MergeSort {
public static void mergeSort(int[] arr,int begin,int end ){
if(begin>=end){
return ;
}
//中间位置
int mid = (begin+end)/2;
//递归分解合并
mergeSort(arr, begin, mid);
mergeSort(arr, mid+1 ,end);
merge(arr,begin,mid,end);
}
/**
* 合并操作
*/
public static void merge(int[] arr, int begin, int mid, int end){
int[] mergeArr=new int[arr.length];
//数组1的指针
int p1 = begin;
//数组2的指针
int p2 = mid+1;
//合并的数组起始位置
int index=begin;
while(p1<=mid && p2<=end){
if(arr[p1]>=arr[p2]){
mergeArr[index++]=arr[p2++];
}else{
mergeArr[index++]=arr[p1++];
}
}
while(p1<=mid){
mergeArr[index++] = arr[p1++];
}
while(p2<=end){
mergeArr[index++] = arr[p2++];
}
for(int i=begin;i<=end;i++){
arr[i] = mergeArr[i];
}
}
public static void main(String[] args) {
int[] arr = {6,5,3,4,2,1,7};
mergeSort(arr, 0, arr.length-1);
System.out.print("排序后数组元素为:");
for (int i=0;i
基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分
实现:
public class QuickSort {
public static int getMid(int[] nums,int low,int high){
int temp=nums[low];
while(low=temp){
high--;
}
nums[low]=nums[high];//如果右边小于中间数 移动到左边
while(low