• 「Java数据结构和算法」手撕快速、归并、基数排序,图解解析 + 代码实现。


    目录

    一、快速排序

    1、基本介绍

    2、代码实现

    二、归并排序

    1、基本介绍

    2、代码实现

    三、基数排序

    1、基本介绍

    2、代码实现


    一、快速排序

    1、基本介绍

            

    以上面的数组为例分析快速排序。

             首先要传入三个值,数组arr[ ] ,最左边下标left ,最右边下标 right。然后将根据左右的下标值计算出中间值mid。

            我们要做的就是将左边的值大于mid的放到右边,将右边小于mid的值放到左边。

            左右两边分别单独循环,左边找到比mid大的数,右边找到比mid小的数。

            两边分别找到符合条件的数后,进行交换。

            然后继续比较并交换,此刻 l 和 mid 都指向3,r 指向 5 。

             这时需要进行判断,如果arr[l] 等于mid  则 r--,如果  arr[r] 等于mid 则 l++ 。此时又进行判断 arr[l] 是否等于arr[r],等于则退出。第一轮就结束了。

            第一次完以后,我们使用递归,递归会重复上面的操作,从而完成排序。

    2、代码实现

    1. //参数传入数组arr , 最左边的下标left,最右边的下标 right
    2. public static void quickSort(int[] arr , int left , int right){
    3. //分别用临时变量代替
    4. int l = left;
    5. int r = right;
    6. //中间的下标
    7. int middle = arr[(left + right) / 2];
    8. //临时变量,用于交换数据
    9. int temp = 0;
    10. //进行循环,只要右边的下标 l 小于 左边的下标 r 就进行循环
    11. while (l < r){
    12. //左边l 到 中间middle 单独循环,找到比middle大的值
    13. while (arr[l] < middle){
    14. l += 1;
    15. }
    16. //中间middle 到 右边 r 单独循环,找到比middle小的值
    17. while (arr[r] > middle){
    18. r -= 1;
    19. }
    20. //退出循环,表示找到,不过先判断 l 是否大于等于 r
    21. //满足就可以退出循环,不需要执行下面的代码了
    22. if(l >= r){
    23. break;
    24. }
    25. //找到的数据进行交换
    26. temp = arr[l];
    27. arr[l] = arr[r];
    28. arr[r] = temp;
    29. //此时进行判断,如果arr[l] 等于middle  则 r--
    30. if(arr[l] == middle){
    31. r -= 1;
    32. }
    33. //如果  arr[r] 等于middle 则 l++
    34. if(arr[r] == middle){
    35. l += 1;
    36. }
    37. }
    38. //退出循环,l 会等于 r,此时要将两者移位,l进行加一,r进行减一
    39. if(l == r){
    40. l += 1;
    41. r -= 1;
    42. }
    43. //第一轮完成后进行递归
    44. //重复上面的方法,向左递归
    45. if(left < r){
    46. //r 继续往前移的,所以左下标为left ,右下标为 r
    47. quickSort(arr, left , r);
    48. }
    49. //重复上面的操作,向右递归
    50. if(right > l){
    51. //l 继续往后移的,所以左下标为 l ,右下标为 right
    52. quickSort(arr, l , right);
    53. }
    54. }


    二、归并排序

     1、基本介绍

    2、代码实现

     ▶ 首先实现合并

    1. public static void merger(int[] arr , int left ,int mid , int right , int[] temp){
    2. int i = left;
    3. int j = mid + 1;
    4. int t = 0;//数组temp的下标
    5. //将arr数组按顺序放入temp 数组
    6. while (i <= mid && j <= right){
    7. //从中间分隔开,左边和右边相互比较
    8. //如果左边更小,先放入temp数组,否则右边先放入
    9. if(arr[i] < arr[j]){
    10. temp[t] = arr[i];
    11. i++;
    12. t++;
    13. }else {
    14. temp[t] = arr[j];
    15. j++;
    16. t++;
    17. }
    18. }
    19. //有可能有一边还没放完,于是继续循环放放入
    20. //左边没放完
    21. while (i <= mid){
    22. temp[t] = arr[i];
    23. t++;
    24. i++;
    25. }
    26. //右边没放完
    27. while (j <= right){
    28. temp[t] = arr[j];
    29. j++;
    30. t++;
    31. }
    32. //将temp中数据拷入到arr
    33. t = 0;
    34. int leftind = left;
    35. //第一次(leftind,right)是(0,1)(2,3)(4,5)(6,7
    36. //第二次(leftind,right)是(0,3)(4,7
    37. //第三次(leftind,right)是(0,7
    38. while (leftind <= right){
    39. arr[leftind] = temp[t];
    40. t++;
    41. leftind++;
    42. }
    43. }

    ▶ 分隔和合并进行递归

    1. public static void mergerSort(int[] arr, int left,int right, int[] temp){
    2. //判断
    3. if (left < right){
    4. //求出中间值
    5. int mid = (left + right) / 2;
    6. //调用自己,向左递归
    7. mergerSort(arr, left, mid , temp);
    8. //调用自己,向右递归
    9. mergerSort(arr , mid + 1, right, temp);
    10. //调用merger进行合并
    11. merger(arr, left , mid, right, temp);
    12. }
    13. }


    三、基数排序

     1、基本介绍

            首先我们需要10个数组,分别对应10个桶,每个桶有对应的下标。

            然后按每个数的个位数大小放入对应的桶中,放好后,按桶的顺序依次取出。

            第二次是看每个数的十位,不及十位的就当做0,依旧是依次放入对应的桶中,并按顺序取出。

            第三次是看每个数的百位,重复上面的操作,最后得到的就是有序的数组。

    2、代码实现

    1. public static void cardinalitySort(int[] arr){
    2. //首先找到数组中最大数的位数
    3. int max = arr[0];
    4. for(int i = 1; i < arr.length - 1; i++ ){
    5. if(arr[i] > max){
    6. max = arr[i];
    7. }
    8. }
    9. int maxLength = (max + "").length();
    10. //定义10个桶,每个桶大小为数组大小
    11. int[][] bucket = new int[10][arr.length];
    12. //定义一个数组来表示每个桶存放的数据
    13. int[] bucketcount = new int[10];
    14. //n是用来进行位数处理的
    15. for(int i = 1, n = 1; i <= maxLength ; i++,n *= 10){
    16. for(int j = 0; j < arr.length ; j++){
    17. //对每位数进行位处理,并放入桶中
    18. int elentData = arr[j] / n % 10;
    19. /*
    20. 放对应的桶中,
    21. bucketcount[elentData]表示对应的桶的数据,
    22. 假如第一个数为579,要放入bucketcount[9](第九个桶)的第一个位置,
    23. 默认初始化为0,所以第一个数放入的位置是bucketcount[9] = 0
    24. */
    25. bucket[elentData][bucketcount[elentData]] = arr[j];
    26. //第一个数放完后,这个桶中数据进行++
    27. //下次再放入这个桶时,bucketcount[9] = 1
    28. bucketcount[elentData]++;
    29. }
    30. int index = 0;
    31. //遍历每一个桶
    32. for(int k = 0; k < bucketcount.length; k++){
    33. //第一次默认为bucketcount[k] = 0
    34. //所以如果第一个数为零,就说明这个桶为空
    35. if(bucketcount[k] != 0){
    36. //有数据,则桶bucketcount[k]就会有对应数据多少的大小,进行遍历
    37. for(int l = 0; l < bucketcount[k] ; l++){
    38. //放入原来的数组
    39. arr[index++] = bucket[k][l];
    40. }
    41. }
    42. //桶中的数放回原数组放完后,进行置空
    43. bucketcount[k] = 0;
    44. }
    45. }
    46. }

  • 相关阅读:
    【Vue】vue.js a标签href里添加参数--20220628
    Android数据结构和算法总结-字符串相关高频面试题算法
    Go中调用外部命令的几种姿势
    SQL优化--关联子查询的前世今生
    PMP每日一练 | 考试不迷路-8.31(包含敏捷+多选)
    websocket详解
    被生活、房贷车贷压得喘不过气的35岁测试工程师,拿什么来谈追求~
    IDEA(安装和使用)
    9、Java——二维数组案例代码详解
    lnmp平台部署web应用,安装Discuz社区平台详细文章——更新中
  • 原文地址:https://blog.csdn.net/yzh2776680982/article/details/126015153