辅车相将网

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

「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、代码实现

//参数传入数组arr , 最左边的下标left,最右边的下标 rightpublic static void quickSort(int[] arr , int left , int right){         //分别用临时变量代替        int l = left;        int r = right;        //中间的下标        int middle = arr[(left + right) / 2];        //临时变量,用于交换数据        int temp = 0;        //进行循环,只要右边的下标 l 小于 左边的下标 r 就进行循环        while (l < r){             //左边l 到 中间middle 单独循环,找到比middle大的值            while (arr[l] < middle){                 l += 1;            }            //中间middle 到 右边 r 单独循环,找到比middle小的值            while (arr[r] >middle){                 r -= 1;            }                        //退出循环,表示找到,不过先判断 l 是否大于等于 r             //满足就可以退出循环,不需要执行下面的代码了            if(l >= r){                 break;            }            //找到的数据进行交换            temp = arr[l];            arr[l] = arr[r];            arr[r] = temp;            //此时进行判断,如果arr[l] 等于middle  则 r--            if(arr[l] == middle){                 r -= 1;            }            //如果  arr[r] 等于middle 则 l++            if(arr[r] == middle){                 l += 1;            }        }                //退出循环,l 会等于 r,此时要将两者移位,l进行加一,r进行减一        if(l == r){             l += 1;            r -= 1;        }                //第一轮完成后进行递归        //重复上面的方法,向左递归        if(left < r){             //r 继续往前移的,所以左下标为left ,右下标为 r            quickSort(arr, left , r);        }        //重复上面的操作,向右递归        if(right >l){             //l 继续往后移的,所以左下标为 l ,右下标为 right            quickSort(arr, l , right);        }    }

二、归并排序

 1、基本介绍

2、代码实现

 ▶ 首先实现合并

public static void merger(int[] arr , int left ,int mid , int right , int[] temp){         int i = left;        int j = mid + 1;        int t = 0;//数组temp的下标        //将arr数组按顺序放入temp 数组        while (i <= mid  && j <= right){             //从中间分隔开,左边和右边相互比较            //如果左边更小,先放入temp数组,否则右边先放入            if(arr[i] < arr[j]){                 temp[t] = arr[i];                i++;                t++;            }else {                 temp[t] = arr[j];                j++;                t++;            }        }        //有可能有一边还没放完,于是继续循环放放入        //左边没放完        while (i <= mid){             temp[t] = arr[i];            t++;            i++;        }        //右边没放完        while (j <= right){             temp[t] = arr[j];            j++;            t++;        }        //将temp中数据拷入到arr        t = 0;        int leftind = left;        //第一次(leftind,right)是(0,1)(2,3)(4,5)(6,7)        //第二次(leftind,right)是(0,3)(4,7)        //第三次(leftind,right)是(0,7)        while (leftind <= right){             arr[leftind] = temp[t];            t++;            leftind++;        }    }

▶ 分隔和合并进行递归

public static void mergerSort(int[] arr, int left,int right, int[] temp){         //判断        if (left < right){             //求出中间值            int mid = (left + right) / 2;            //调用自己,向左递归            mergerSort(arr, left, mid , temp);            //调用自己,向右递归            mergerSort(arr , mid + 1, right, temp);            //调用merger进行合并            merger(arr, left , mid, right, temp);        }    }

三、基数排序

 1、基本介绍

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

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

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

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

2、代码实现

public static void cardinalitySort(int[] arr){         //首先找到数组中最大数的位数        int max = arr[0];        for(int i = 1; i < arr.length - 1; i++ ){             if(arr[i] >max){                 max = arr[i];            }        }        int maxLength = (max + "").length();        //定义10个桶,每个桶大小为数组大小        int[][] bucket = new int[10][arr.length];        //定义一个数组来表示每个桶存放的数据        int[] bucketcount = new int[10];        //n是用来进行位数处理的        for(int i = 1, n = 1; i <= maxLength ; i++,n *= 10){             for(int j = 0; j < arr.length ; j++){                 //对每位数进行位处理,并放入桶中                int elentData = arr[j] / n % 10;                /*                      放对应的桶中,                  bucketcount[elentData]表示对应的桶的数据,                  假如第一个数为579,要放入bucketcount[9](第九个桶)的第一个位置,                  默认初始化为0,所以第一个数放入的位置是bucketcount[9] = 0                */                bucket[elentData][bucketcount[elentData]] = arr[j];                //第一个数放完后,这个桶中数据进行++,                //下次再放入这个桶时,bucketcount[9] = 1                bucketcount[elentData]++;            }            int index = 0;            //遍历每一个桶            for(int k = 0; k < bucketcount.length; k++){                 //第一次默认为bucketcount[k] = 0                //所以如果第一个数为零,就说明这个桶为空                if(bucketcount[k] != 0){                     //有数据,则桶bucketcount[k]就会有对应数据多少的大小,进行遍历                    for(int l = 0; l < bucketcount[k] ; l++){                         //放入原来的数组                        arr[index++] = bucket[k][l];                    }                }                //桶中的数放回原数组放完后,进行置空                bucketcount[k] = 0;            }        }    }

未经允许不得转载:辅车相将网 » 「Java数据结构和算法」手撕快速、归并、基数排序,图解解析 + 代码实现。