1.冒泡排序(BubbleSort 稳定 算法复杂度最好O(n) 最坏是O(n2) )
冒泡排序 通过相邻两个数的比较,交换位置,从后往前排
public class BubbleSort {
//对相邻的数进行对比,符合条件就交换位置
public static int[] BubbleSort( int[] arr) {
for (int i = 0; i <arr.length; i++)
{
for (int j = 0; j<arr.length-i-1; j++)
{
if (arr[j] > arr[j + 1])
{
int temp;
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
public static void printArr(int [] arr){
for(int num:arr){
System.out.print(num+" ");
}
}
public static void main(String[] args) {
int [] arr={1,8,6,2,5,4,9,3,7};
printArr(BubbleSort(arr));
}
}
代码执行过程比较简单。就是重复的交换相邻的数,每轮都有最大的一个数被排在最后,直到排序完成
2.插入排序(InsertSort 稳定 算法复杂度 最好O(n) 最坏O(n2) )
插入排序 在排好序的n个数的数组中,将第n+1个数插入到指定位置,使其变成排好序的n+1个数组,
选取元素插入到指定位置
public class InsertSort {
public static int [] InsertSort(int [] arr){
for(int i=1;i<arr.length;i++){
int j=0;
//判断是否插入,和插入数值的位置
if(arr[i]<arr[i - 1]){
//保留当前数
int temp=arr[i];
//判别之前的数是否比当前值小如果是,将比当前小的数都向后移一个位置,将temp值插入所有比它大的数前面,
for(j = i - 1 ; j >= 0 && temp < arr[j] ; j--)
{ //将位置后移一位
arr[j+1]=arr[j];
}
//将当前数插入到指定位置
arr[j+1]=temp;
}
}
return arr;
}
public static void printArr(int [] arr){
for(int num:arr){
System.out.print(num+" ");
}
}
public static void main(String[] args) {
int [] arr={2,5,6,7,1,4,3,8,9};
printArr(InsertSort(arr));
}
}
得到的结果是
代码执行过程
判断1 比前一个小
记录1的值 ,将2,5,6,7后移 arr={2,2,5,6,7,4,3,8,9},再将1插入到2前面 arr={1,2,5,6.7,4,3,8,9}
后面以此类推
3.选择排序(SelectionSort 不稳定 算法复杂度 O(n2))
选择排序 ,将一列数组从中选择最大或最小的数放到起始位置,再从未排序的数中选择最大或最小的排在上个数之后。
public class SelectionSort {
public static int [] SelectionSort(int [] arr){
for(int i = 0;i<arr.length;i++){
//先记录当前位置
int minIndex=i;
//比较未排好的数,如果小于记录的值,就记录下位置,如果之后位置的值小于当前位置就交换两者的值,
for(int j=i;j<arr.length;j++)
{
if(arr[j]<arr[minIndex])
{
//每次循环结束都有一个最小的数,
minIndex=j;
}
}
//交换值
int temp=arr[i];
arr[i]=arr[minIndex];
arr[minIndex]=temp;
}
return arr;
}
public static void printArr(int [] arr){
for(int num :arr){
System.out.print(num + " ");
}
}
public static void main(String[] args) {
int [] arr={2,5,6,7,1,4,3,8,9};
printArr(SelectionSort(arr));
}
}
执行过程
判断1是最小的数 记录1 的索引位置,直接与第一个交换位置
arr={1,5,6,7,2,4,3,8,9}
后面以此类推
4.快速排序(QuickSort 不稳定 算法复杂度O(nlogn) )
//算法复杂度 O(nlogn)
//把所有数值根据基准数分为左右两个部分,左边小于基准数,右边大于基准数,再把左边和右边的部分各自从内部取一个基准数再次排序,以此类推,直到左右两边只有一个数为止即left=right
public class QuickSort2 {
public static void quickSort(int arr[]){
//如果数组为0,或者len为0就直接退出
//定义的长度的量
int len ;
if(0==arr.length || 0==(len=arr.length)|| 1==len ){
return;
}
sort(arr,0,len-1);
}
private static void sort(int[] arr, int left, int right) {
//如果开始位置大于结束位置就退出
if(left>right){
return;
}
//定义基准数,最左和最右两个位置
int base =arr[left];
int i=left,j=right;
//left!=right就继续
while(i!=j){
//从最右边开始,如果大于基准数,且left<j,获取大于基准数的索引位置
while(arr[j]>=base&&i<j)
j--;
}
//从最左边开始,如果小于基准数,且right>i;获取小于基准数的索引位置
while(arr[i]<=base&&i<j){
i++;
}
//根据索引位置交换
if(i<j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
//将基准数插入
arr[left]=arr[i];
arr[i]=base;
//分为两个部分对左右都开始进行快排
//左边从left开始到基准数索引位置-1结束
//右边从基准数索引位置+1结束
sort(arr, left, i-1);
sort(arr, i+1, right);
}
public static void printArr(int arr[]){
for(int num :arr){
System.out.print(num+" ");
}
}
public static void main(String[] args) {
int [] arr ={5,2,6,9,1,3,4,8,7};
quickSort(arr);
printArr(arr);
}
}
{5,2,6,9,1,3,4,8,7}
第一次以5为基准 进行交换6,4位置 {5,2,4,9,1,3,6,8,7}
第二次 交换 3,9 位置 {5,2,4,3,1,9,6,8,7}
第三次 将基准数放到中间 交换 1,5位置 {1,2,4,3,5,9,6,8,7}
第四次 将数组分成基准数中间分成左右两个部分,
左边取基准数1,2 都没变化 ,取4 交换 3,4 位置 {1,2,3,4,5,9,6,8,7}
右边 取基数9 交换 7,9 位置 {1,2,3,4,5,7,6,8,9}
取基准数 7 交换 7,6 位置 {1,2,3,4,5,6,7,8,9}
取基准数 8 没变化
取基准数 9 没变化
5.归并排序(MergeSort 稳定 算法复杂度O(nlogn))
先将数组分成两个部分 再将数组分成n个部分再将n个部分进行排序,再将i个部分合并成j个进行排序,最后j个排序后的结果进行比较判别填入数组
public class MergeSort {
private static void MergeSort(int[] arr, int start , int end) {
if(start<end){
int mid = (start+end)/2;
// start表示从子序列的哪个索引开始, mid表示子序列中间的位置, end表示子序列结束的位置
//将数组分成左右两边进行归并排序
MergeSort(arr,start,mid);
MergeSort(arr,mid+1,end);
Merge(arr,start,mid,end);
}
}
private static void Merge(int[] arr, int start, int mid, int end) {
int L = mid-start+1; //左边的长度
int R = end-mid; //右边的长度
int left [] = new int[L]; //左边的数组
int right [] = new int[R]; //右边的数组
// k用来表示当前遍历的数组arr的索引
int i=0,j=0,k=0;
// 分别给left和right赋值
// 从左边开始
for(i=0,k=start; i<n1; i++,k++){
left [i] = arr[k];
}
// 从右边开始
for(j=0,k=mid+1; j<n2; j++,k++){
right [j] = arr [k];
}
// 比较大小,从小到大排列
for(i=0,j=0,k=start ; i<L&&j<R; k++){
if(left [i] > right [j]){
arr[k] = right [j];
j++;
// 逐个比较left和right的大小,如果left[i]的数比right 大就往right下一个查找直到找到大于left[i]的数或right结束为止
// 对比得到最小的值填入arr数组
}else{
// 将对比得到的小的值填入arr数组
arr[k] = left [i];
i++;
}
}
// 将两个数组中剩下的数放到a中
if(i<L){
for(j=i; j<n1; j++,k++){
arr[k] = left [j];
}
}
if(j<R){
for(i=j; i<n2; i++,k++){
arr[k] = right [i];
}
}
}
public static void printArr(int [] arr){
for(int num :arr){
System.out.print(num+" ");
}
}
public static void main(String[] args) {
int[] arr ={5,6,2,3,1,8,9,7,4};
MergeSort(arr, 0, arr.length-1);
printArr(arr);
}
}
代码执行过程:
如下面代码我给出的数组是5,6,2,3,1,8,9,7,4 因为总共9个数字,所以mid=4 左边5个 右边四个,并根据依次往下拆分
第一次 将5 放入left,6 放入right,再将left和right 进行比较 排序,arr={5,6,2,3,1,8,9,7,4}
第二次 将5,6放入 left ,2放入right ,进行比较大小,填入arr= { 2,5,6,3,1,8,9,7,4 }
第三次 将 3放入 left ,1 放入 right ,进行排序 ,arr={ 2,5,6,1,3,8,9,7,4 }
第四次 将 2,5,6 填入left ,1,3 填入right ,比较大小,填入arr= {1,2,3,5,6,8,9,7,4}
第五次 将 8放入 left ,9 放入 right ,比较排序 ,填入arr={1,2,3,5,6,8,9,7,4}
第六次 将 7放入 left ,4放入right,比较排序 ,填入 arr={1,2,3,5,6,8,9,4,7}
第七次 将 8,9 放入 left ,4,7 放入 right ,比较排序 填入 arr={1,2,3,5,6,4,7,8,9}
第八次 将 1,2,3,5,6放入left ,将4,7,8,9放入 right 比较排序填入 arr={1,2,3,4,5,6,7,8,9 }
6.希尔排序(ShellSort 不稳定 升级版的冒泡排序 算法复杂度 O((n)3/2))
没有快速排序快,但是最坏和最好的算法复杂度相差不是很多,跟O(n2)比起来又快了不少
//插入排序的加强版 通过不同的步长,来进行排序 步长为1就是插入排序
//例如 有 7,8,3,9,11,6 六个数 步长为 2 分为7,3,11 8,9,6
//步长为3 分为 7,9 8,11 3,6
//根据步长 来调整
public class ShellSort {
public static int [] ShellSort(int [] arr){
shell(arr, getIncreatment(arr));
return arr;
}
private static void shell(int [] arr ,int ic){
int i,j,k;
int len=arr.length;
for(i=0;i<len;i++ ){
//分配步长数组
for(j=i+ic;j<len;j+=ic){
if(arr[j]<arr[j-ic]){
int temp =arr[j];
for(k=j-ic ; k>=0 && temp<arr[k] ; k-=ic){
//在对应步长内的数组进行插入排序 先将值后移一位,再将记录的值插入
arr[k+ic]=arr[k];
}
//插入记录的值
arr[k+ic]=temp;
}
}
}
}
//确定增量increatement ,可以自己添加
public static int getIncreatment(int arr []){
int increate=arr.length;
if(increate%2!=0){
increate=1;
}else if (0==increate%2) {
increate=2;
}
System.out.println("increatement : "+increate);
return increate;
}
public static void printArr(int arr[]){
int count =0;
for(int num: arr){
System.out.print(num+" ");
}
}
public static void main(String[] args) {
int [] arr={2,5,6,7,1,4,3,8,9,10};
System.out.println("arr.length : "+arr.length);
printArr(ShellSort(arr));
}
}
当步长是1 的时候相当于插入排序
当步长是2的时候,分成两个数组 2,6,1,3,9 和5,7,4,8,10 排序后的结果是
1,2,3,6,9 4,5,7,8,10 合并成数组就是 1,4,2,5,3,7,6,8,9,10