排序算法 | 算法

80 阅读2分钟

常见的排序列表

image.png

选择排序

  • 指定第一个位置为最小值;
  • 从其余值中选择最小值与指定的最小位置比较,如果其余值中选择的最小值较小,进行值交换
public class SelectionSort {
    public static void main(String[] args){
        int arr[] = {7,4,1,5,8,6,2,3,9};
        print(arr);
        for(int i=0; i<arr.length; i++) {
            int minPos = i;

            for (int j = i+1; j < arr.length; j++) {
                minPos = arr[j] < arr[minPos] ? j : minPos;
            }
            System.out.println("minPos:" + minPos);

            swap(arr, i,minPos);

            System.out.println("经过第" + i +"次循环后,数组的内容:");
            print(arr);
        }
    }

    static void swap(int arr[], int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    static void print(int arr[]){
        for (int i=0; i<arr.length; i++){
            System.out.print(arr[i] + " ");
        }
    }
}

image.png

冒泡排序

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

完整代码:

public class BubbleSort {
    public static void main(String args[]){
        int arr[] = {7,5,2,1,4,6,3,9,8};
        Bubble(arr);
        print(arr);
    }

    static void Bubble(int[] arr) {
        for(int i=arr.length-1; i>0; i--){
            for(int j=0;j<i;j++){
                if(arr[j]>arr[j+1]) swap(arr,j,j+1);
            }
        }
    }

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

    static void print(int[] arr) {
        for(int k=0;k<arr.length;k++){
            System.out.print(arr[k]+" ");
        }
    }
}

考虑到时间复杂度最佳情况下(序列原本就是正序),进一步改进使得时间复杂度是O(n)。完善后的代码是:

    static void BestBubble(int[] arr) {
        boolean didSwap;
        for(int i=arr.length-1; i>0; i--){
            didSwap = false;
            for(int j=0;j<i;j++){
                if(arr[j]>arr[j+1]) {
                    swap(arr, j, j + 1);
                    didSwap = true;
                }
            }
            if(didSwap == false)
                return;
        }
    }

希尔排序

public class ShellSort {

    public static void main(String args[]){
        int arr[] = {9,6,11,3,5,12,8,7,10,15,14,4,1,13,2};

        sort(arr);
        print(arr);
    }

    static void sort(int[] arr) {
        int h=1;
        while(h<= arr.length / 3){
            h = 3*h+1;
        }
        //gap使用Knuth序列
        for(int gap = h; gap>0; gap=(gap-1)/3){ //还有一种比Knuth序列效率低一些的,是gap /=2
            //下面是插入排序的代码改编过来的
            for(int i=gap;i<arr.length;i++){
                for(int j=i;j>gap-1;j-=gap){
                    if(arr[j-gap]>=arr[j])
                        swap(arr,j,j-gap);
                }
            }
        }

    }
    static void print(int[] arr) {
        for(int k=0; k<arr.length;k++){
            System.out.print(arr[k] + " ");
        }
    }

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

    }
}

归并排序

public class MergeSort {
    public static void main(String args[]){
        int arr[] = {1,4,7,8,3,6,9};
        merge(arr);
    }

    static void print(int[] arr) {
        for (int k =0;k<arr.length;k++){
            System.out.print(arr[k] + " ");
        }
    }

    static void merge(int[] arr) {
        int mid = arr.length/2;
        int temp[] = new int[arr.length];

        int i = 0;
        int j = mid + 1;
        int k = 0;

        while(i <= mid && j < arr.length){
            if(arr[i] <= arr[j]){
                temp[k++] = arr[i++];
            }else{
                temp[k++] = arr[j++];
            }
        }

        while(i<=mid) temp[k++] = arr[i++];

        while (j<arr.length) temp[k++] = arr[j++];
        print(temp);
    }
}

快速排序

public class QuickSort {
    public static void main(String args[]){
        int arr[] = {7,3,2,8,1,9,5,4,6};
        sort(arr,0,arr.length-1);

        print(arr);
    }

    public static void sort(int[] arr, int leftBound, int rightBound) {
        if(leftBound >= rightBound) return;
        int mid = partition (arr,leftBound,rightBound);
        sort(arr,leftBound,mid-1);
        sort(arr,mid + 1,rightBound);
    }
    static int partition(int arr[],int leftBound,int rightBound){
        int pivot = arr[rightBound];
        int left = leftBound;
        int right = rightBound - 1;

        while(left <= right){
            while (left <= right && arr[left]<=pivot) left++;
            while (left <= right && arr[right]>pivot) right--;

            if (left < right ) swap(arr,left,right);
        }
        swap(arr,left,rightBound);
        return left;
    }

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

    static void print(int[] arr) {
        for (int k=0;k<arr.length;k++){
            System.out.print(arr[k] + " ");
        }
    }
}

计数排序

import java.util.Arrays;

public class CountSort {
    public static void main(String args[]){
        int[] arr = {2,4,2,3,7,1,1,0,0,5,6,9,8,5,7,4,0,9};
        int[] result = sort(arr);

       System.out.println(Arrays.toString(result));
    }

    static int[] sort(int[] arr) {
        int[] result = new int[arr.length];
        int[] count = new int[10];

        for(int i=0; i<arr.length; i++){
            count[arr[i]]++;
        }

        System.out.println(Arrays.toString(count));

        for(int i=0,j=0;i<count.length;i++){
            while(count[i]-- > 0) result[j++] = i;
        }
        return result;
    }
}

基数排序

原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

import java.util.Arrays;

public class RadixSort {
    public static void main(String[] args){
        int[] arr = {421,240,115,532,305,430,124};

        int[] result = sort(arr);
        System.out.println((Arrays.toString(result)));
    }
    //基数排序
    public static int[] sort(int[] arr){
        int[] result = new int[arr.length];
        int[] count = new int[10];

        for(int i=0;i<3;i++){
            int division =(int)Math.pow(10,i);
            System.out.println(division);
            for(int j=0; j<arr.length; j++){
                int num = arr[j]/division % 10;
                System.out.println(num + " ");
                count[num]++;
            }
            System.out.println();
            System.out.println(Arrays.toString(count));

            for(int m=1; m<count.length;m++){
                count[m] = count[m] + count[m-1];
            }
            System.out.println(Arrays.toString(count));

            for(int n=arr.length-1;n>=0;n--){
                int num = arr[n]/division % 10;
                result[--count[num]] = arr[n];
            }

            System.arraycopy(result,0,arr,0,arr.length);
            Arrays.fill(count,0);
        }
        return result;
    }

    static void findMax(int[] a, int n){
        for(int j=0;j<n;j++){
            if(a[j] > a[j+1]) swap(a,j,j+1);
        }
    }
    static void swap(int[] a,int i,int j){
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

image.png