1.冒泡算法

平均时间复杂度为O(n²);

从小到大排序:

形式1(把大数往右对齐,即右大对齐策略):

public class bubbleSort {  
public  bubbleSort(){  
     int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};  
    int temp=0;  
    for(int i=0;i<a.length-1;i++){  
        for(int j=0;j<a.length-1-i;j++){  
        if(a[j]>a[j+1]){  
            temp=a[j];  
            a[j]=a[j+1];  
            a[j+1]=temp;  
        }  
        }  
    }  
    for(int i=0;i<a.length;i++)  
        System.out.println(a[i]);     
}  
}  

形式2:(把小数往左对齐,即左小对齐策略)

public class bubble_sort {

	static void bubble_sort(int[] unsorted)
    {
        for (int i = 0; i < unsorted.length; i++)
        {
            for (int j = i+1; j < unsorted.length; j++)
            {
                if (unsorted[i] > unsorted[j])
                {
                    int temp = unsorted[i];
                    unsorted[i] = unsorted[j];
                    unsorted[j] = temp;
                }
            }
        }
    }

   public static void main(String[] args)
    {
        int[] x = { 0, 6, 2, 4, 1, 5, 9 };
        bubble_sort(x);
        System.out.println(Arrays.toString(x));
    }
}

2.快速排序:

时间复杂度为O(nlogn)  

public static void quickSort(int[] arr, int startIndex, int endIndex) {
        if(arr != null && arr.length > 0) {
            int start = startIndex, end = endIndex;
            //target是本次循环要排序的元素,每次循环都是确定一个元素的排序位置,这个元素都是开始下标对应的元素
            int target = arr[startIndex];
            //开始循环,从两头往中间循环,相遇后循环结束
            while(start<end) {
                //从右向左循环比较,如果比target小,就和target交换位置,让所有比target小的元素到target的左边去
                while(start < end) {
                    if(arr[end] < target) {
                        swap(arr, start, end);
                        break;
                    }else {
                        end--;
                    }
                }

                //从左向右循环比较,如果比target大,就和target交换位置,让所有比target大的元素到target的右边去
                while(start < end) {
                    if(arr[start] > target) {
                        swap(arr, start, end);
                        break;
                    }else {
                        start++;
                    }
                }
            }
            //确定target的排序后,如果target左边还有元素,继续递归排序
            if((start-1)>startIndex) {
                quickSort(arr, startIndex, start-1);
            }
            //确定target的排序后,如果target右边还有元素,继续递归排序
            if((end+1)<endIndex) {
                quickSort(arr, end+1, endIndex);
            }
        }
    }

参考:

https://blog.csdn.net/boy_chen93/article/details/85049274

https://blog.csdn.net/u011998957/article/details/88080093

3.归并排序

 时间复杂度是O(nlogn)

public class MergeSort {
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

参考:https://www.cnblogs.com/chengxiao/p/6194356.html

4.堆排

时间复杂度为O(nlogn); 不稳定排序。

import java.util.Arrays;

/**
 * 堆排序
 */
public class HeapSort {
    public static void main(String []args){
        int []arr = {11,7,18,3,5,4,1,6,10,9};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        //1.构建大顶堆
        for(int i=arr.length/2-1;i>=0;i--){
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr,i,arr.length);
        }
        //2.调整堆结构+交换堆顶元素与末尾元素
        for(int j=arr.length-1;j>0;j--){
            swap(arr,0,j);//将堆顶元素与末尾元素进行交换
            adjustHeap(arr,0,j);//重新对堆进行调整
        }

    }

    /**
     * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
     * @param arr
     * @param i
     * @param length
     */
    public static void adjustHeap(int []arr,int i,int length){
        int temp = arr[i];//先取出当前元素i
        for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
            if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
                k++;
            }
            if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                arr[i] = arr[k];
                i = k;
            }else{
                break;
            }
        }
        arr[i] = temp;//将temp值放到最终的位置
    }

    /**
     * 交换元素
     * @param arr
     * @param a
     * @param b
     */
    public static void swap(int []arr,int a ,int b){
        int temp=arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}

参考:https://www.cnblogs.com/chengxiao/p/6129630.html

 

5.插入排序

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1) 
public static void insertionSort(int[] nums) {

    if (nums == null || nums.length < 2) {
        return;
    }

    for(int i = 1; i < nums.length; i++) {
        for(int j = i - 1; j >= 0 && nums[j] > nums[j + 1]; j--) {
            ArrayUtils.swap(nums, j, j + 1);
        }
    }

}
public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

上面的算法的缺点:在第i-1趟插入时,需要把第i个元素插入到前面的i-1个元素中,该算法总是从i-1个元素开始逐个比较之前的每个元素,直到找到第i个元素的插入位置,这显然没有利用前面0~i-1个元素已经有序的特点

优化:在0~i-1个有序元素给第i个元素寻找插入的位置时,使用二分查找法可以有效提高查找插入位置的时间效率,经过优化的插入排序称为折半插入排序,折半插入排序的时间复杂度为O(n*logn)

/**
 * 折半插入排序
 */
public static void binaryInsertionSort(int[] nums) {

    if (nums == null || nums.length < 2) {
        return;
    }

    for(int i = 1; i < nums.length; i++) {
        int temp = nums[i];
        // 通过二分查找找到插入的位置
        int insertIndex = findInsertIndex(nums, 0, i - 1, nums[i]);
        // 插入位置之后的元素依次向后移动
        for(int j = i; j > insertIndex; j--) {
            nums[j] = nums[j - 1];
        }
        // 更新插入位置的值
        nums[insertIndex] = temp;
    }

}

/**
 * 在有序数组 nums 的[L, R]部分上,找到 value 的插入位置
 */
public static int findInsertIndex(int[] nums, int L, int R, int value) {

    while(L <= R) {
        int mid = L + ((R - L) / 2);
        if(value > nums[mid]) {
            L = mid + 1;
        } else {
            R = mid - 1;
        }
    }

    return L;

}

参考:https://www.jianshu.com/p/d2cf77f78b3e

 

6.选择排序

时间复杂度 O(n²) 。

public class SelectionSort {
    public static void main(String[] args) throws Exception {
        int []arr = {11,7,18,3,5,4,1,6,10,9};
        arr = sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static int[] sort(int[] sourceArray) throws Exception {
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        // 总共要经过 N-1 轮比较
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i;

            // 每轮需要比较的次数 N-i
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    // 记录目前能找到的最小值元素的下标
                    min = j;
                }
            }

            // 将找到的最小值和i位置所在的值进行交换
            if (i != min) {
                int tmp = arr[i];
                arr[i] = arr[min];
                arr[min] = tmp;
            }

        }
        return arr;
    }
}

参考:https://www.runoob.com/w3cnote/selection-sort.html

7.希尔排序

非稳定排序。

public static void shellSort(int[] arr){
        int N = arr.length;
        //进行分组,最开始的增量gap为数组长度的一半
        for (int gap = N>>1; gap >0; gap>>=1) {
            //对各个分组进行插入排序
            for(int i=gap;i<N;i++){
               //将arr[i]插入到所在分组的正确位置上
                insertI(arr,gap,i);
            }
        }
    }
    /**
     * @Author obrain
     * @Description //将arr[i]查到所在分组的正确位置上
     * @Date 14:16 2020/6/20
     * @Param [arr, gap, i]
     * @return void
    */
    static void insertI(int[] arr, int gap, int i){
        int temp = arr[i];
        int j;
        //插入时按组进行插入(组内元素两两相隔gap)
        for ( j = i-gap; j>=0 && temp<arr[j]; j-=gap) {
            arr[j+gap] = arr[j];
        }
        arr[j+gap] = temp;
    }

参考:https://www.imooc.com/article/284892

8.双轴快排

单轴快排、双轴快排:参考:https://blog.csdn.net/Holmofy/article/details/71168530

 

9.更多算法参考

https://www.runoob.com/w3cnote_genre/algorithm


本文转载:CSDN博客