常见排序算法[java实现](由难到易)
912. 排序数组
快排
class Solution {
? ?// 快排
? ?public int[] sortArray(int[] nums) {
? ? ? ?return quickSort(nums,0,nums.length-1);
? }
? ?int[] quickSort(int[] nums, int left, int right)
? {
? ? ? ?partition(nums,left,right);
? ? ? ?return nums;
? }
? ?int partition(int[] nums,int left,int right)
? {
? ? ? ?if(left>right) return -1;
? ? ? ?int l=left,r=right,divi=nums[l];
? ? ? ?while(true)
? ? ? {
? ? ? ? ? ?while(l<=r && nums[l]<=divi) l++;
? ? ? ? ? ?while(l<=r && nums[r]>divi) r--;
? ? ? ? ? ?if(l>r) break;
? ? ? ? ? ?swap(nums,l,r);
? ? ? }
? ? ? ?swap(nums,left,r);
? ? ? ?partition(nums,left,r-1);
? ? ? ?partition(nums,r+1,right);
? ? ? ?return r;
? }
? ?void swap(int[] nums,int l,int r)
? {
? ? ? ?int temp = nums[l];
? ? ? ?nums[l] = nums[r];
? ? ? ?nums[r] = temp;
? }
}
912. 排序数组
归并
class Solution {
? ?// 归并排序
? ?public int[] sortArray(int[] nums) {
? ? ? ?return sort(nums,0,nums.length-1);
? }
? ?public int[] sort(int[] nums,int l,int r)
? {
? ? ? ?if(l<r)
? ? ? {
? ? ? ? ? ?int mid = (l+r)/2;
? ? ? ? ? ?sort(nums,l,mid);
? ? ? ? ? ?sort(nums,mid+1,r);
? ? ? ? ? ?merge(nums,l,r,mid);
? ? ? }
? ? ? ?return nums;
? }
? ?void merge(int[] nums,int left,int right,int mid)
? {
? ? ? ?int oldL = left;
? ? ? ?// System.out.println(Arrays.toString(nums)+ " coming l="+left+" r="+right);
? ? ? ?int l = left,r=mid+1;
? ? ? ?int[] temp = new int[right-left+1];
? ? ? ?int k = 0;
? ? ? ?while(l<=mid && r<=right)
? ? ? {
? ? ? ? ? ?if(nums[l]<nums[r])
? ? ? ? ? {
? ? ? ? ? ? ? ?temp[k++] = nums[l++];
? ? ? ? ? }else{
? ? ? ? ? ? ? ?temp[k++] = nums[r++];
? ? ? ? ? }
? ? ? }
? ? ? ?while(l<=mid) temp[k++] = nums[l++];
? ? ? ?while(r<=right) temp[k++] = nums[r++];
? ? ? ?for(int i=0;i<k;i++)
? ? ? {
? ? ? ? ? ?nums[left++] = temp[i];
? ? ? }
? ? ? ?// System.out.println(Arrays.toString(nums)+ " out l="+oldL+" r="+right);
? }
}
912. 排序数组
计数排序
-
开辟一个values数组,以数组下标来间接表示原数组的元素值,values[i]表示该值出现了多少次 -
values长度?
-
数组下标从零开始,如何表示[min,max]的映射空间
-
那values数组开很大很大,满足映射空间,可以下标直接保存原值吗?
-
理论上,不可以
-
原值存在负数,数组溢出 -
num-min,可以将负数转为正值表示
class Solution {
? ?public int[] sortArray(int[] nums) {
? ? ? ?int max = Arrays.stream(nums).max().orElseGet(() -> 0);
? ? ? ?int min = Arrays.stream(nums).min().orElseGet(() -> 0);
? ? ? ?int[] values = new int[max-min+1];
? ? ? ?for(int num : nums)
? ? ? {
? ? ? ? ? ?values[num-min]++; // 下标位移min
? ? ? }
? ? ? ?int k=0;
? ? ? ?for(int i=0;i<values.length;i++)
? ? ? {
? ? ? ? ? ?while(values[i]>0)
? ? ? ? ? {
? ? ? ? ? ? ? ?nums[k++] = i+min;// (i+min)-->原先放入values的值
? ? ? ? ? ? ? ?values[i]--;
? ? ? ? ? }
? ? ? }
? ? ? ?return nums;
? }
}
912. 排序数组
堆排序:
-
堆:满足一定条件的满二叉树,可以用数组来表示 -
满足的条件:
-
构建堆的下沉操作
-
堆删除操作[自上而下操作]
-
堆排序
class Solution {
? ?// 堆排序
? ?public static int[] sortArray(int[] arr)
? {
? ? ? ?int n = arr.length;
? ? ? ?// 构建堆,将前一半元素下沉
? ? ? ?for (int i = n; i >=0 ; i--) {
? ? ? ? ? ?downAdjust(arr,i,n-1);
? ? ? }
? ? ? ?// 每次移除最大值,置于数组尾部
? ? ? ?for (int i = n-1; i >=0 ; i--) {
? ? ? ? ? ?swap(arr,0,i);
? ? ? ? ? ?downAdjust(arr,0,i-1);
? ? ? }
? ? ? ?return arr;
? }
?
? ?/**
? ? * 下沉的过程,其实为了维护堆的性质(nums[i]>nums[2*i+1] && nums[i]>nums[2*i+2])
? ? * @param arr 堆,用数组表示的满二叉树 ?
? ? * @param down: 本次下沉的元素下标,找到一个合适的位置,满足左右节点都不大于下沉节点
? ? * @param n: 堆的最大节点下标
? ? */
? ?// downAdjust
? ?public static void downAdjust(int[] arr,int down,int n){
? ? ? ?if(down>n) return;
? ? ? ?int child = 2 * down + 1;
? ? ? ?while(child<=n)
? ? ? {
? ? ? ? ? ?if(child>n) break; // 此时,下沉节点为叶子节点,不进行下沉
? ? ? ? ? ?int right = child+1;
? ? ? ? ? ?if(right<=n && arr[right]>arr[child]) // 若right存在,并且比较大,此时最大者为right子节点
? ? ? ? ? {
? ? ? ? ? ? ? ?child = right;
? ? ? ? ? }
? ? ? ? ? ?// 是否进行交换,看下沉节点是否比两个子节点还大[大根堆]
? ? ? ? ? ?if(arr[down]>=arr[child]) break;
? ? ? ? ? ?swap(arr,down,child);
? ? ? ? ? ?down = child;
? ? ? ? ? ?child = down * 2 + 1;
? ? ? }
? }
? ?public static void swap(int[] arr,int l,int r){
? ? ? ?int t=arr[l];
? ? ? ?arr[l]=arr[r];
? ? ? ?arr[r]=t;
? }
}
912. 排序数组
选择排序:超时
class Solution {
? ?public int[] sortArray(int[] arr){
? ? ? ?for (int i = 0; i < arr.length - 1; i++) {
? ? ? ? ? ?int min = i;
? ? ? ? ? ?for (int j = i+1; j < arr.length; j++) {
? ? ? ? ? ? ? ?min = (arr[j]<arr[min])?j:min;
? ? ? ? ? }
? ? ? ? ? ?swap(arr,i,min);
? ? ? }
? ? ? ?return arr;
? }
? ?static void swap(int[] arr,int l,int r)
? {
? ? ? ?int t = arr[l];
? ? ? ?arr[l] = arr[r];
? ? ? ?arr[r] = t;
? }
}
912. 排序数组
冒泡排序:超时
class Solution {
? ?public static int[] sortArray(int[] arr){
? ? ? ?for (int i = 0; i < arr.length - 1; i++) {
? ? ? ? ? ?for (int j = 0; j < arr.length-i-1; j++) {
? ? ? ? ? ? ? ?if(arr[j+1]<arr[j])
? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? swap(arr,j+1,j);
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? }
? ? ? ?return arr;
? }
? ?static void swap(int[] arr,int l,int r)
? {
? ? ? ?int t = arr[l];
? ? ? ?arr[l] = arr[r];
? ? ? ?arr[r] = t;
? }
}
912. 排序数组
插入排序
class Solution {
? ?public static int[] sortArray(int[] nums)
? {
? ? ? ?int j=0;
? ? ? ?for (int i = 1; i < nums.length; i++) {
? ? ? ? ? ?int insert = nums[i];
? ? ? ? ? ?for (j = i-1; j >=0 ; j--) {
? ? ? ? ? ? ? ?if(nums[j]>insert)
? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ?nums[j+1] = nums[j];
? ? ? ? ? ? ? ? ? ?continue;
? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?break;
? ? ? ? ? }
? ? ? ? ? ?nums[j+1] = insert;
? ? ? }
? ? ? ?return nums;
? }
}
912. 排序数组
基数排序
class Solution {
? ?public int[] sortArray(int[] nums) {
? ? ? ?return sort(nums);
? }
? ?public static int[] sort(int[] arr)
? {
? ? ? ?// 1. 预处理arr,让arr全部都是正数
? ? ? ?int min = Arrays.stream(arr).min().getAsInt();
? ? ? ?arr = Arrays.stream(arr).map(ar -> ar - min).toArray();
? ? ? ?// 2. 计算arr中最大值的位数bit
? ? ? ?int max = Arrays.stream(arr).max().getAsInt();
? ? ? ?int bit = getBit(max);
? ? ? ?// 3. 初始化基数桶
? ? ? ?ArrayList<LinkedList<Integer>> bucket = new ArrayList<>(10);
? ? ? ?for (int i = 0; i < 10; i++) {
? ? ? ? ? ?bucket.add(new LinkedList<>());
? ? ? }
? ? ? ?int bi = 1;
? ? ? ?// 4. 循环bit次
? ? ? ?for (int i = 0; i < bit; i++) {
? ? ? ? ? ?// 将数组元素放入bucket,以当前的基数为下标
? ? ? ? ? ?for (int j = 0; j < arr.length; j++) {
? ? ? ? ? ? ? ?int index = (arr[j] / bi) % 10;
? ? ? ? ? ? ? ?bucket.get(index).add(arr[j]);
? ? ? ? ? }
? ? ? ? ? ?int k = 0;
? ? ? ? ? ?// 将桶数据依次回流数组
? ? ? ? ? ?for (LinkedList<Integer> buck : bucket) {
? ? ? ? ? ? ? ?for (Integer num : buck) {
? ? ? ? ? ? ? ? ? ?arr[k++] = num;
? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?// 桶清空
? ? ? ? ? ? ? ?buck.clear();
? ? ? ? ? }
? ? ? ? ? ?bi*=10;
? ? ? }
? ? ? ?// 最后返回时,需要将arr的值转回去
? ? ? ?arr = Arrays.stream(arr).map(ar->ar+min).toArray();
? ? ? ?return arr;
? }
? ?static int getBit(int num)
? {
? ? ? ?if(num==0) return 1;
? ? ? ?int bit=0;
? ? ? ?while (num!=0)
? ? ? {
? ? ? ? ? ?bit++;
? ? ? ? ? ?num/=10;
? ? ? }
? ? ? ?return bit;
? }
}
912. 排序数组
桶排
class Solution {
? ?// 桶排序
? ?public int[] sortArray(int[] nums) {
? ? ? ?return sort(nums);
? }
? ?public static int[] sort(int[] nums)
? {
? ? ? ?// set
? ? ? ?Set<Integer> set = new HashSet<>();
? ? ? ?// 数值区间[min,max]分为block块,分别排序后,合并
? ? ? ?int min = Arrays.stream(nums).min().getAsInt();
? ? ? ?int max = Arrays.stream(nums).max().getAsInt();
? ? ? ?// 定义block块
? ? ? ?int block = nums.length;
? ? ? ?// 每个小区间
? ? ? ?int d = (max-min)/block;
? ? ? ?//
? ? ? ?int total = Math.max(max-min,1);
? ? ? ?// 定义block个桶
? ? ? ?List<List<Integer>> bucket = new ArrayList<>(block);
? ? ? ?for(int i=0;i<block;i++) bucket.add(new LinkedList());
? ? ? ?// 将数据按照大小区间入桶
? ? ? ?for(int num : nums)
? ? ? {
? ? ? ? ? ?int index = (num-min)/(d+1); // (num-min)-->当前元素相对于min的偏移量,偏移量除以d+1-->向下取整
? ? ? ? ? ?set.add(index);
? ? ? ? ? ?bucket.get(index).add(num);
? ? ? }
? ? ? ?// 将每个桶排序,并收集结果
? ? ? ?int k = 0;
? ? ? ?for(List<Integer> path : bucket)
? ? ? {
? ? ? ? ? ?Collections.sort(path);
? ? ? ? ? ?for(int val : path)
? ? ? ? ? {
? ? ? ? ? ? ? ?nums[k++] = val;
? ? ? ? ? }
? ? ? }
? ? ? ?return nums;
? }
}
912. 排序数组
希尔排序
class Solution {
? ?public int[] sortArray(int[] nums) {
? ? ? ?// 分组插入
? ? ? ?int n = nums.length;
? ? ? ?// 分组
? ? ? ?int gap = n/2;
? ? ? ?while(gap>=1)
? ? ? {
? ? ? ? ? ?for(int i=gap;i<n;i++)
? ? ? ? ? {
? ? ? ? ? ? ? ?insert(nums,gap,i); //以gap的间距,构成的组,插入排序
? ? ? ? ? }
? ? ? ? ? ?gap/=2;
? ? ? }
? ? ? ?return nums;
? }
? ?static void insert(int[] nums,int gap,int insert)
? {
? ? ? ?int temp = nums[insert];
? ? ? ?int j;
? ? ? ?for(j=insert-gap;j>=0;j-=gap)
? ? ? {
? ? ? ? ? ?if(temp<nums[j]) nums[j+gap] = nums[j];
? ? ? ? ? ?else break;
? ? ? }
? ? ? ?nums[j+gap] = temp; ?
? }
}
|