排序算法

对排序算法做一个总结吧。先提交,回头再补吧

分类

比较类:

  1. 插入法:
  • 插入排序

遍历未排序的列,将遍历到的每个元素插入到有序序列的适当位置。

  • 希尔排序。

先将待排序的数组分成若干个子数组排序

  1. 选择法:包括选择排序和堆排序
  • 选择排序

选择第 i 小的元素与第 i- 1 的位置交换

  1. 交换法:包括冒泡排序和快速排序

非比较类

  1. 计数排序

  2. 桶排序

  3. 基数排序

复杂度和稳定性

不稳定排序口诀:一 堆 希尔 快 选!

排序算法

1. 插入法

插入排序

public class InsertSort {
    public static void main(String[] args) {
        int arr[] = {17, 3, 25, 14, 20, 9};
        System.out.println("排序前的数组:");
        System.out.println(Arrays.toString(arr));

        insertSort(arr);
        System.out.println("排序后的数组:");
        System.out.println(Arrays.toString(arr));
    }


    public static void insertSort(int arr[]) {
        int len = arr.length;
        //数组的第一个元素默认有序的,所以从 1 开始遍历
        for (int i = 1; i < len; i++) {
            int temp = arr[i];
            int j = i - 1;
            //遍历待排序元素前面的元素,若大于待排序的元素后移一位
            while(j >= 0 && arr[j] > temp){
                arr[j + 1] = arr[j];
                j--;
            }
            //遍历结束,将待排序的元素插入到所在的位置
            arr[j + 1] = temp;//注意是 j + 1
        }
    }
}

希尔排序

希尔排序:也是一种插入排序
1,把记录按下标的一定增量分组(例如有n个数,先分成n/2组,对每组进行排序。
2,然后分成n/2/2组,进行排序,
3,直到n/2/2...=1,
排序算法

public class ShellSort {
    public static void main(String[] args) {
        int arr[] = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
        shellSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void shellSort(int arr[]) {
        //第一个for循环是将原数组分组
        for (int gap = arr.length / 2; gap > 0 ; gap /= 2) {

            //后面同插入排序一样,间隔 1 换成了 gap
            for (int i = gap; i < arr.length ; i++) {
                int j = i - gap;
                int temp =arr[i];
                while(j >= 0 && arr[j] > temp) {
                    arr[j+gap] = arr[j];
                    j -= gap;
                }
                arr[j + gap] = temp;
            }

        }

    }
}

选择排序

在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

public class SelectSort {
    public static void main(String[] args) {
        for (int i = 0; i < arr.length - 1; i++) {
            int temp = 0;
            int index = i; // 用来保存最小值得索引

            // 寻找第i个小的数值
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[index] > arr[j]) {
                    index = j;
                }
            }

            // 将找到的第i个小的数值放在第i个位置上
            temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
        }
    }
}

堆排序

3. 堆的概念

堆是一棵顺序存储的完全二叉树。

完全二叉树排序算法

,称为大顶堆;,称为小顶堆。

  • 小根堆:或者每个结点的值都小于或等于其左右孩子结点的值。

  • 大根堆:每个结点的值都大于或等于其左右孩子结点的值。

排序算法

同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子:

排序算法

该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

冒泡排序

它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换

排序算法

public class BubbleSort {
    public static void main(String[] args) {
        int arr[] = {17, 3, 25, 14, 20, 9};
        System.out.println("排序前的数组:");
        System.out.println(Arrays.toString(arr));

        bubbleSort(arr);
        System.out.println("排序后的数组:");
        System.out.println(Arrays.toString(arr));
    }


    public static void bubbleSort(int arr[]) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) {

            for (int j = arr.length - 1; j > i; j--) {
                // 比较相邻的元素,如果前面的数大于后面的数,则交换
                if (arr[j - 1] > arr[j]) {
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
}

快速排序

基本思想

1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;

​ 2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;

​ 3.对左右两个分区重复以上步骤直到所有元素都是有序的。

  • 优化:基准值的选取 选择中间值 int m = low + (high - low) / 2;//数组中间元素的下标
public class QuickSort {
    public static void main(String[] args) {
        int n = 100000;
        Random random = new Random(n);
        int[] array = {3,5,4,3,2,1,5,7,4,0};

        System.out.println("排序前数组:" + Arrays.toString(array));
        quickSort(array,0,array.length - 1);

        System.out.println(Arrays.toString(array));
    }
    //快排的实现
    public static void quickSort(int[] arr, int l, int r) {
        if(l >= r) return;
        int i = l , j = r;
        
        while (i < j) {
            while (i < j && arr[j] >= arr[l]) j--;
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i ,j);
        }
        swap(arr, i, l);
        quickSort(arr, l, i - 1);
        quickSort(arr, i + 1, r);
    }
    //交换数组中的两个元素
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}