十大经典排序

1.冒泡排序

    public static void bubbleSort(int nums[]) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = 0; j < nums.length - i - 1; j++) {
                if(nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
            System.out.println(Arrays.toString(nums));
        }
    }

就是相邻元素进行比较,把大的元素往后移,小的元素往左移,最后达到升序。我们可以看到程序在第五次排序的 时候其实是已经有序了,这里可以优化了一下,加个判断提前终止排序。

2.选择排序

   public static void selectSort(int arr[]) {
        int n = arr.length;
        // 循环遍历数组
        for (int i = 0; i < n - 1; i++) {
            // 找到最小元素的索引
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            // 交换找到的最小元素和当前位置元素
            int temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
            System.out.println(Arrays.toString(arr));
        }
    }

选择排序就是在每一次循环中,将该元素与后面的元素进行比较,找到最小值然后进行交换。

假设原数组是:64, 25, 12, 22, 11

i = 0 的时候       arr[i] = 64 ,就会与后面的所有元素比较,记录最小元素的下标值,然后进行交换。

[11, 25, 12, 22, 64]。以此类推。。。。

[11, 12, 25, 22, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64],经过四轮排序。

3.插入排序

    public static void main(String[] args) {
        int[] array = {64, 25, 12, 22, 11};
        insertSort(array);
    }
    public static void insertSort(int arr[]){
        for (int i = 1; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i;

            while (j > 0 && tmp < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }

            if (j != i) {
                arr[j] = tmp;
            }
            System.out.println(Arrays.toString(arr));
        }
    }

主要原理就是,先记录当前的值为tmp,然后与左边排好序的值进行比较,如果是小于它,就将左边的值覆盖右边的值  就是  arr[j] = arr[j-1],直到j == 0。

当i = 1 的时候,tmp = 25  j = 1

25 < 65              然后覆盖左边的值  变成   64,64,12,22,11

j = 0  i = 1   符合条件   arr[0] = 25    变成  [25, 64, 12, 22, 11]

当 i = 2 , tmp = 12  j = 2

12 < 64              25,64,64,22,11    j = 1

12 < 25             25,25,64,22,11  j = 0  

此时j == 0    arr[0] = tmp = 12   转换成 [12, 25, 64, 22, 11]

以此类推。。。。。

经过四轮排序。 

[25, 64, 12, 22, 11]
[12, 25, 64, 22, 11]
[12, 22, 25, 64, 11]
[11, 12, 22, 25, 64]

4.希尔排序

    public static void shellSort(int[] arr) {
        int length = arr.length;
        int temp;
        for (int step = length / 2; step >= 1; step /= 2) {
            for (int i = step; i < length; i++) {
                temp = arr[i];
                int j = i;
                while (j >= step && arr[j - step] > temp) {
                    arr[j] = arr[j - step];
                    j -= step;
                }
                arr[j] = temp;
                System.out.println(Arrays.toString(arr));
            }
            System.out.println("----------------------");
        }
    }

希尔排序主要是对插入排序进行了优化,引入了步长这个概念。分割成了若干个子序列进行插入排序,当setp =1 的时候然后再总体进行一次插入排序。

第一轮

[12, 25, 64, 22, 11]
[12, 22, 64, 25, 11]
[11, 22, 12, 25, 64]
----------------------

第二轮
[11, 22, 12, 25, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64]
----------------------

我们来列举一下第一轮的过程。

当step = 2 

i = 2          temp = 12           j = 2

进行一次插入排序  判断条件  (j >= 2  && arr[j - step]  >  12) 满足条件

进行覆盖  64,25,64,22,11  。然后 j == 0 退出条件。

arr[0] = 12       ----->>>>       [12, 25, 64, 22, 11]

i = 3  temp = 22    j =3

arr[j - step] = 25

第一次判断(j  >=  2 && arr[j - step] >  22 ) 满足条件

进行覆盖   12,25,64,25,11          此时j = 1   小于step  退出条件

arr[1] = 22           ------------->       [12, 22, 64, 25, 11]

i = 4 temp = 11  j = 4

arr[j - step] = 64

第一次判断(j  >=  2 && arr[j - step] >  11) 满足条件

进行覆盖  12,22,64,25,64  j = 2  满足条件

j = 2

arr[j - step] = 12

第二次判断  (j  >=  2 && arr[j - step] >  11)满足条件

进行覆盖  12,2212,25,64    j = 0 退出

arr[0] = 11     ------------->>>>>>>>>>>  [11, 22, 12, 25, 64]

5.归并排序

   public static void main(String[] args) {
        int[] array = {64, 25, 12, 22, 11};
        mergeSort(array,0, array.length - 1);
    }
    public  static void mergeSort(int arr[],int left, int right) {
        if(left < right) {
            int mid = (right - left) / 2 + left;
            mergeSort(arr, left, mid);
            mergeSort(arr,mid + 1, right);
            merge(arr,left,mid,right);
            System.out.println(Arrays.toString(arr));
        }
    }
    public static void merge(int arr[], int left, int mid, int right) {
        //临时数组记录此处的数值
        int temp[] = new int[right - left + 1];
        //左指针
        int l = left;
        //右指针
        int r = mid + 1;
        //记录数组下标
        int k = 0;
        while (l <= mid && r <= right) {
            if(arr[l] < arr[r]) {
                temp[k++] = arr[l++];
            } else {
                temp[k++] = arr[r++];
            }
        }
        //将多于的元素重新填充
        while(l <= mid) {
            temp[k++] = arr[l++];
        }
        while (r <= right) {
            temp[k++] = arr[r++];
        }
        //重新赋值到原数组
        for(int i = 0; i < temp.length; i++) {
            arr[i + left] = temp[i];
        }
    }

我们来看看流程图,就很直观了。就是将数组不断的切分,化成左右两份,然后去比较大小,最后再去合并数组。合并的逻辑主要是用一个临时数组去存储记录。

6.快速排序

  public static void main(String[] args) {
        int[] ints = {30, 34, 22, 11, 90};
        quickSort(ints,0, ints.length - 1);
    }
    public static void quickSort(int arr[], int left, int right) {
        if(left < right) {
            int mid = partition(arr, left, right);
            quickSort(arr, left, mid - 1);
            quickSort(arr,mid + 1, right);
        }
    }
    public static int partition(int arr[], int left, int right ) {
        //选择左边第一个数作为基准数
        int pivot = left;
        int index=  pivot + 1;
        for (int i = index; i <= right; i++) {
            if(arr[i] < arr[pivot]) {
                swap(arr,i,index);
                index++;
            }
        }
        swap(arr,index - 1,pivot);
        System.out.println(Arrays.toString(arr));
        return index - 1;
    }
    private static void swap(int arr[], int left, int right) {
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }

核心主要是分区,这里以左边第一个作为基准数,排序过程是要将小于基准数放到左边,大于基准数放到右边。

这里举一个例子就能明白了。

当第一次进入partition函数中的时候。

left = 0  right = 4  arr[pivot] = 30

i = 1  index = 1   34 > 30    30, 34, 22, 11, 90

i = 2  index = 1   22 < 30   交换  ---------->>>>>>>>30,22,34,11,90  index = 2

i = 3 index = 2    11 < 30  交换  ------------>>>>>>>>30,22,11,34,90 index = 3

i = 4 index = 3    90 > 30   结束了for循环

此时的数组是 30,22,11,34,90  index = 3

如果我们要实现小于基准数放到左边,大于基准数放到右边。         

那么就需要index - 1   =  2  然后去交换,变成 11,22,30,34,90 

往后的递归就是分成左右两边不断地去重复这个过程,直到全部排序完。

  • 31
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mikey689

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值