算法:JAVA排序算法【自学收藏向】

算法:排序算法

最优

有一句谚语:“All roads lead to Rome.” 面对一个编程问题时,我们有多种方法来实现;

但是怎样才能判断哪种方法才是最优的呢?
在这里插入图片描述

我们运行程序,当然希望程序越快,占内存越小;但是速度与空间,就像杠杆中的力臂与力,两者必须做出取舍。如果选择速度快,即时间复杂度小,程序所占内存空间的大小就会增加;而希望程序占内存小,程序运行的速度也会随之受影响。

当然,现如今大家考虑最优一般是从速度(时间复杂度)的角度出发。

时间频度

时间频度,一个算法中的语句执行的次数称为时间频度,记作T(n)

随着程序规模的变大,时间频度的常数项、低次项、系数可以忽略

例子

同样是计算100以内数的和,我们有2种实现方法

int total =0;
//1, for循环相加
int end=100;
for(int i=1;i<=end;i++){
    total += i;
}

//2,利用等差数列公式
total =(1+end)*end /2;

第一种方法的时间频度:T(n) = n+1 //因为进入循环+判断

第二种方法的时间频度:T(n) = 1 //直接计算得出结果

时间复杂度

时间复杂度,也叫大O时间复杂度,表示方法是O(n)

由于程序规模的变大,时间频度有些地方可以忽略,从而产生了时间复杂度

例如,T(n) = n^2 +7n+6 ; T(n) = 3n^2 +2n+2

两者虽然时间频度不同,但是时间复杂度确实一样,都是O(n^2)

常见的时间复杂度例子
常数阶O(1)12
对数阶O(logn)5log2n+20
平方阶(双层for循环)O(n^2)3n^2+2n+1
线性阶O(n)2n+3
线性对数阶O(nlogn)2n+3nlog2n+19
立方阶(三层for循环)O(n^3)6n3+2n2+3n+4
指数阶(要尽量避免)O(2^n)2^n+3
k次方阶O(n^k)n^k

时间复杂度排序,由小变大:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(n^k) < O(2^n)

冒泡排序(Bubble Sorting)

用2个指针比较2个数,从左往右,如果第1个大于第2个,两个数交换位置

因为排序的数字是一个一个累加的,所以称之为冒泡排序

在这里插入图片描述

在这里插入图片描述

  1. 将指针从左往右遍历,需要一次for循环
  2. 至多遍历4次,才能达到最终的顺序,还需要for循环

第1次遍历完后,数组最后一个元素可以不用比较了, 所以for循环大小-1,也就是说:

第一次 ---- array.length -1

第二次 ---- array.length -2

第三次 ---- array.length -3

第四次 ---- array.length -4

所以:

package Sorting;

import java.util.Arrays;

public class BubbleSorting {
	public static void main(String[] args) {
		int[] array = {3, 9, -1, 10, -2};
		int tmp =0;
		for(int i=array.length-1; i>0; i--) {
			for(int j=0;j<i;j++) {
				if(array[j] > array[j+1]) {
					tmp = array[j];
					array[j] = array[j+1];
					array[j+1] =tmp;
				}
			}
		}
		System.out.println(Arrays.toString(array));
	}
}

冒泡排序优化

假设给出的数组原来就是有序的,或仅仅经过2次就正序了,我们可以直接跳出循环,中止程序

package Sorting;

import java.util.Arrays;

public class BubbleSorting {
	public static void main(String[] args) {
//		int[] array = {3, 9, -1, 10, -2};
		int[] array = {3,2,6,4,5};
		int tmp =0;
		boolean flag=false; //flag判断是否进行了排序交换
		for(int i=array.length-1; i>0; i--) {
			for(int j=0;j< i;j++) {
				if(array[j] > array[j+1]) {
					tmp = array[j];
					array[j] = array[j+1];
					array[j+1] =tmp;
					flag = true;
				}
			}
			System.out.println("第"+(array.length-i)+"次遍历");
			System.out.println(Arrays.toString(array));
			if(!flag) {
				break;
			}else {
				flag = false; //用于判断下一次有没有交换,如果没有,表示数据已正序
			}
		}
	}
}

在这里插入图片描述

第1次遍历在交换顺序,第2次遍历判断是否正序

因为有2个嵌套式的循环,冒泡排序的时间复杂度是n^2

选择排序(Select Sorting)

选择排序和冒泡排序很像,但是两者还是有所区别

在选择排序中,我们要选择最小的数据,并把最小的数据放到整个数组最前面

当我们遍历数组查找最小元素时,我们仅仅记下最小元素下标,只有当前数组遍历结束时,数组才会发生交换,效率相比于冒泡排序(每次遍历都要相互交换)大大提高。

int[] array = {101,34,119,1};
//第一轮将最小的移到最前面 1, 34, 119, 101
//第二轮将剩下的最小的移到前面 1, 34, 119, 101
//第三轮将剩下的最小的移到前面 1,34,101,119

从上我们可以看出,每次循环遍历后,初始位置都会向后挪1位(因为最小的已经在前面了)

我们依次比较剩下的数,所以需要array.length-1次才能将数从小到大依次移到前面

package Sorting;

import java.util.Arrays;

public class SelectionSorting {

	public static void main(String[] args) {
		int[] array = {101,34,119,1};
		
		for(int i=0;i<array.length-1;i++) {
			int smallest=i;
			for(int j=i;j<array.length;j++) {
				if(array[j]< array[smallest]) {
					smallest = j;//我们仅仅记下最小元素下标
				}
			}
            
            //结束遍历后才能发生交换
			if(i!=smallest) {
				int temp = array[i];
				array[i] = array[smallest];
				array[smallest] = temp;
			}
			System.out.println("第"+(i+1)+"轮循环:"+Arrays.toString(array));
		}
		
		
	}

}

在这里插入图片描述

插入排序(Insert Sorting)

在这里插入图片描述

第1轮:我们从第2个数开始,把第2个数和前面的数进行比较,从右往左,如果第2个数小于第1个数,两者交换位置

第2轮:我们从第3个数开始,把第3个数和前面的数进行比较(0,1),如果第3个数小于第2个数,两者交换,如果交换后,第1个数比交换后的第2个数大,继续交换,直至到最后

第n轮:从第n+1个数开始,把第n+1个数和前面的数(n个数)进行比较,找个合适的地方插入(这就是插入排序)

一共有array.length-1轮

package Sorting;

import java.util.Arrays;

public class InsertSorting {

	public static void main(String[] args) {
		int[] array = { 93, 54, 77, 31, 44, 226, 55 };
		int temp;
		//换位法
		for (int i = 1; i < array.length; i++) {
			for (int j = i; j > 0; j--) {
				if (array[j] < array[j - 1]) {
					temp = array[j];
					array[j] = array[j - 1];
					array[j - 1] = temp;
				}else {
					break;
				}
			}
//移位法
//			temp = array[i];
//			int j =i;
//			while(j>0 && temp<array[j-1]) {
//				array[j] = array[j - 1];
//				j--;
//			}
//			
//			if (j != i) {
//                array[j] = temp;
//            }
			System.out.println("第" + i + "轮:" + Arrays.toString(array));
		}

	}

}

在这里插入图片描述

希尔排序(Shell Sorting)

希尔排序是由希尔所发现的,所以命名为Shell Sorting. 希尔排序本质上还是插入排序Insert Sorting, 但是希尔排序运行效率相比上面大大提升。

第一轮:

排序前要先给数据分组,让数组的长度/2,即array.length /2, 得出的是组中数据的间隔。我们在分好的组内进行插入排序,间距此时是array.length 除以2。第1组插入排序进行完后,移入第2组,依次进行,直到最后一组。

第二轮:

总体和上面一样,但是每组数据的间隔是之前的一半,(array.length/2)/2

直到最后一轮,步数为1,普通的插入排序,但是遍历次数减少

点击查看源网页

package Sorting;

import java.util.Arrays;

public class ShellSorting {

	public static void main(String[] args) {
		int[] array = {59,48,75,107,86,23,37,59,65,14 };
		
		int length = array.length;
		int temp;
		//步长
		for(int step = length/2;step >0; step /=2) {
			//插入算法循环次数
			for(int i=step;i<length;i++) {
				//控制插入算法的比较和交换
				//移位法
				temp = array[i];
				int j =i;
				if(array[j] < array[j-step]) {
					while(j>=step && temp<array[j-step]) {
						array[j] = array[j - step];
						j-=step;
					}
				}
				
	            array[j] = temp;
	            
				
				/**
				 * 换位法
				for(int j=i;j>=step;j-=step) {
					if(array[j]<array[j-step]) {
						temp = array[j];
						array[j] = array[j-step];
						array[j-step] = temp;
					}
					else
						break;
				}
				*/
			}
            System.out.println(Arrays.toString(array));
		}
		
				

	}

}

在这里插入图片描述

快速排序(Quick Sorting)

快速排序是一种非常经典的排序算法,它的运行效率非常高,当然快排属于空间换时间的一类,因为要使用递归。

基本思路:

选取数组最中间的数为基数(以这个数为基准),用2个指针分别从最左边和最右边读取数据,将小于基数的数放在左边,大于基数的数放在右边。最后排完,小于的都在左侧,大的都在右侧。我们继续进行递归,由于此时左侧和右侧的指针都指向基数,为了分别进行左排序递归和右排序递归,左侧指针右移1格,右指针左移1格。

图解:

(哎,图片不清晰)

在这里插入图片描述

package Sorting;

import java.util.Arrays;

public class QuickSorting2 {
	public static void main(String[] args) {
//		int[] array = {59,48,75,107,86,23,37,59,65,14 };
		int[] array = {77,26,93,17,54,31,44,55,20 };
		QuickSort(array, 0, array.length-1);
		System.out.println(Arrays.toString(array));
	}
	
	public static void QuickSort(int[] array, int left, int right) {
		int l =left;
		int r =right;
		int temp;
		int pivot = array[(left+right)/2];
		while(l<r) {
			//左边往右走
			while(array[l]<pivot) {
				l+=1;
			}
			//右边往左走
			while(array[r]>pivot) {
				r -=1;
			}
			if(l>=r) {
				break;
			}
			
			temp =array[l];
			array[l]=array[r];
			array[r] = temp;
			
			//交换后发现array[l] == pivot的值 r--;前移
			if(array[l] == pivot) {
				r -=1;
			}
			
			//交换后发现array[r] == pivot的值 l++;前移
			if(array[r] == pivot) {
				l +=1;
			}
			
		}
		
        //递归
		if(left<r) {
			QuickSort(array, left, r-1);
		}
		if(right>l) {
			QuickSort(array, l+1, right);
		}
	}
}

以第一个数为基准的快速排序

package Sorting;

import java.util.Arrays;

public class QuickSorting3 {

	public static void main(String[] args) {
		int[] array = {77,26,93,17,54,31,44,55,20 };
		Sort(array, 0, array.length-1);
		System.out.println(Arrays.toString(array));
	}
	
	public static void Sort(int[] array, int left, int right) {
		int l = left;
		int r = right;
		int pivot = array[left]; //以第一个数为基准
		while(true) {
			while(array[r] >= pivot&&l<r) {
				r-=1;
			}
			if(l<r) {
				array[l] =array[r];
				l+=1;
			}
			while(array[l] <= pivot&&l<r) {
				l +=1;
			}
			if(l<r) {
				array[r] = array[l];
				r -=1;
			}
			if(l==r) {
				array[l] = pivot;
                break;
			}
		}
		
		if(left<r) {
			Sort(array, left, r-1);
		}
		
		if(right > l) {
			Sort(array, l+1, right);
		}
	}

}

归并排序(Merge Sorting)

归并排序和上面的快速排序思想上类似,都用到了经典的分治算法(divide and conquer),即先将复杂的问题划分divide成小的问题然后递归求解,然后再conquer(把各个划分阶段的答案修补在一起)

Divide

在这里插入图片描述

Conquer

在这里插入图片描述

为了方便操作,我们传进去的数组会被复制,输出的是一个新的数组,这个数组就是排序好的数组

Divide分的时候要采用递归,每次分2份,直到数组每个元素都被分别分在1个数组中

当递归完后,回溯时从最后一个数组开始,即一个一个元素的数组,返回上一层,将此时的数组赋给left或right,接着调用Conquer,把2个数组排序放入一个新的数组,然后再返回,依次进行,直到全部排序完成

package Sorting;

import java.util.Arrays;

public class MergeSorting {
	public static void main(String[] args) {
//		int[] array = {59,48,75,107,86,23,37,59,65,14 };
		int[] array = {77,26,93,17,54,31,44,55,20 };
		MergeSort(array);
		System.out.println(Arrays.toString(array));
		
	}
	
	public static void MergeSort(int[] arr) {
		int[] arr2 = Divide(arr);
		for(int i=0;i<arr2.length;i++) {
			arr[i]=arr2[i];
		}
	}
	
	public static int[] Divide(int[] arr) {
		int pivot = (arr.length)/2;
		if(pivot>=1) {
			int[] left = new int[pivot];
			int[] right = new int[arr.length-pivot];
			for(int i=0;i<left.length;i++) {
				left[i] = arr[i];
			}
			for(int j=0;j<right.length;j++) {
				right[j]=arr[pivot+j];
			}
			
//			System.out.println(Arrays.toString(left));
//			System.out.println(Arrays.toString(right));
//			System.out.println("---");
			left = Divide(left);
			right = Divide(right);
		
			return Conquer(left, right);
		}
		return arr;
	
	}
	
	
	public static int[] Conquer(int[] arr1, int[] arr2) {
		int[] temp = new int[arr1.length+arr2.length];
		int cur =0;
		int left =0;
		int right =0;
		while(true) {
			if(arr1[left]<arr2[right]) {
				temp[cur] = arr1[left];
				cur++;
				left++;
			}
			else if(arr1[left] > arr2[right]) {
				temp[cur] = arr2[right];
				cur++;
				right++;
			}
			else {
				temp[cur] =arr1[left];
				cur++;
				left++;
				temp[cur] = arr2[right];
				cur++;
				right++;
			}
			if(left>=arr1.length) {
				for(int i=right;i<arr2.length;i++) {
					temp[cur] = arr2[i];
					cur++;
				}
				break;
			}
			else if(right>=arr2.length){
				for(int i=left;i<arr1.length;i++) {
					temp[cur] = arr1[i];
					cur++;
				}
				break;
			}
		}
		
		return temp;
	}
	
}

基数排序(Radix Sorting)

基数排序是特殊的桶排序

步骤:

  1. 先将数组按个位排序分类,分好后一个一个放入原数组
  2. 再把数组按照十位排序分类,同上
  3. 直到分到原数组中最大数的位数,例如最大数是3789,我们最后就要按照千位来排序

在这里插入图片描述

由小到大,这样依次我们就完成对数组的排序

package Sorting;

import java.util.Arrays;

public class RedixSorting {

	public static void main(String[] args) {
		int[] array = {77,26,93,17,54,107,31,44,55,20 };
		RadixSort(array);
		System.out.println(Arrays.toString(array));
	}
	
	
	public static void RadixSort(int[] array) {
		//找出最大的一位
		int Max =0;
		for(int i=0;i<array.length;i++) {
			if(array[Max] <array[i]) {
				Max =i;
			}
		}
		
		//得出最大一位的个数
		int count=0;
		int temp =array[Max];
		while(temp>0) {
			temp /= 10;
			count++;
		}
		for(int j=0;j<count;j++) {
			busket(array, pow(10,j));
		}
		
		
	}
	
	//计算一个数的几次方
	public static int pow(int num, int exp) {
		if(exp==0) {
			return 1;
		}
		for(int i=0;i<exp-1;i++) {
			num *= num;
		}
		return num;
	}
	
	public static void busket(int[] array, int digit) {
		//创建一个桶用来记录数据
		int[][] bucket = new int[10][array.length];
		
		//创建一个数组来记录每个桶里面元素的个数
		int[] itemNum = new int[10];
		
		for(int i=0;i<array.length;i++) { 
		
			int no = array[i]/digit%10; //哪一个桶
			bucket[no][itemNum[no]] = array[i] +10;
			itemNum[no] +=1;
		}
		
		
		int index=0;
		for(int j=0;j<10;j++) {
			for(int k=0;k<bucket.length;k++) {
				if(bucket[j][k] !=0) {
					array[index] = bucket[j][k]-10;
					bucket[j][k] =0;
					index++;
				}
				else {
					break;
				}
			}
			itemNum[j] =0;
		}
		index =0;
		
		
	}

}

排序算法的时间复杂度比较

排序法平均时间最差情况
冒泡O(n^2)O(n^2)
交换O(n^2)O(n^2)
选择O(n^2)O(n^2)
插入O(n^2)O(n^2)
基数O(logR B)O(logR B)
ShellO(nlogn)O(n^s) 1<s<2
快排O(nlogn)O(n^2)
归并O(nlogn)O(nlogn)
O(nlogn)O(nlogn)

术语:

稳定:两个数据在排序后任然保持之前的相对前后位置

时间复杂度:算法运行所消耗的时间

img

测试程序

package Sorting;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSortingTime {
	public static void main(String[] args) {
		int[] array = new int[80000];
		
		Init(array);
		System.out.println("BubbleSorting");
		PrintTime("Start: ");
		BubbleSorting(array);
		PrintTime("End: ");
		System.out.println();

		Init(array);
		System.out.println("SelectionSorting");
		PrintTime("Start: ");
		SelectionSorting(array);
		PrintTime("End: ");

		System.out.println();
		Init(array);
		System.out.println("InsertSorting");
		PrintTime("Start: ");
		InsertSorting(array);
		PrintTime("End: ");
		
		System.out.println();
		Init(array);
		System.out.println("ShellSorting");
		PrintTime("Start: ");
		ShellSorting(array);
		PrintTime("End: ");
		
		
		System.out.println();
		Init(array);
		System.out.println("QuickSorting");
		PrintTime("Start: ");
		QuickSort(array, 0, array.length-1);
		PrintTime("End: ");
		
		System.out.println();
		Init(array);
		System.out.println("QuickSorting2");
		PrintTime("Start: ");
		QuickSort2(array, 0, array.length-1);
		PrintTime("End: ");
		
		System.out.println();
		Init(array);
		System.out.println("MergeSorting");
		PrintTime("Start: ");
		MergeSort(array);
		PrintTime("End: ");
		
		System.out.println();
		Init(array);
		System.out.println("RedixSorting");
		PrintTime("Start: ");
		RadixSort(array);
		PrintTime("End: ");
	}

	public static void Init(int[] array) {
		for (int i = 0; i < array.length; i++) {
			array[i] = (int) (Math.random() * 80000);
		}
	}

	public static void PrintTime(String words) {
		Date date1 = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		String time = sdf.format(date1);
		System.out.println(words + time);
	}

	public static void BubbleSorting(int[] array) {
		int tmp = 0;
		boolean flag = false; // flag判断是否进行了排序交换
		for (int i = array.length - 1; i > 0; i--) {
			for (int j = 0; j < i; j++) {
				if (array[j] > array[j + 1]) {
					tmp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = tmp;
					flag = true;
				}
			}
			if (!flag) {
				break;
			} else {
				flag = false; // 用于判断下一次有没有交换,如果没有,表示数据已正序
			}
		}
	}

	public static void SelectionSorting(int[] array) {
		for (int i = 0; i < array.length - 1; i++) {
			int smallest = i;
			for (int j = i; j < array.length; j++) {
				if (array[j] < array[smallest]) {
					smallest = j;
				}
			}
			if (i != smallest) {
				int temp = array[i];
				array[i] = array[smallest];
				array[smallest] = temp;
			}
		}

	}

	public static void InsertSorting(int[] array) {
		int temp;
		for (int i = 1; i < array.length; i++) {
			for (int j = i; j > 0; j--) {
				if (array[j] < array[j - 1]) {
					temp = array[j];
					array[j] = array[j - 1];
					array[j - 1] = temp;
				}else {
					break;
				}
			}
		}
	}
	
	public static void ShellSorting(int[] array) {
		int length = array.length;
		int temp;
		for(int step = length/2;step >0; step /=2) {
			for(int i=step;i<length;i++) {
				temp = array[i];
				int j =i;
				if(array[j] < array[j-step]) {
					while(j>=step && temp<array[j-step]) {
						array[j] = array[j - step];
						j-=step;
					}
				}
				if (j != i) {
	                array[j] = temp;
	            }
//				for(int j=i;j>=step;j-=step) {
//					if(array[j]<array[j-step]) {
//						temp = array[j];
//						array[j] = array[j-step];
//						array[j-step] = temp;
//					}
//					else
//						break;
//				}
			}
		}
	}
	
	public static void QuickSort(int[] array, int left, int right) {
		int l =left;
		int r =right;
		int temp;
		int pivot = array[(left+right)/2];
		while(l<r) {
			//左边往右走
			while(array[l]<pivot) {
				l+=1;
			}
			//右边往左走
			while(array[r]>pivot) {
				r -=1;
			}
			if(l>=r) {
				break;
			}
			
			temp =array[l];
			array[l]=array[r];
			array[r] = temp;
			
			//不进行下面的操作程序会卡死
			//交换后发现array[l] == pivot的值 r--;前移
			if(array[l] == pivot) {
				r -=1;
			}
			
			//交换后发现array[r] == pivot的值 l++;前移
			if(array[r] == pivot) {
				l +=1;
			}
			
		}
		
		if(left<r) {
			QuickSort(array, left, r-1);
		}
		if(right>l) {
			QuickSort(array, l+1, right);
		}
	}
	
	public static void QuickSort2(int[] array, int left, int right) {
		int l = left;
		int r = right;
		int pivot = array[left];
		while(true) {
			while(array[r] >= pivot&&l<r) {
				r-=1;
			}
			if(l<r) {
				array[l] =array[r];
				l+=1;
			}
			while(array[l] <= pivot&&l<r) {
				l +=1;
			}
			if(l<r) {
				array[r] = array[l];
				r -=1;
			}
			if(l==r) {
				array[l] = pivot;
				break;
			}
		}
		
		if(left<r) {
			QuickSort2(array, left, r-1);
		}
		
		if(right > l) {
			QuickSort2(array, l+1, right);
		}
	}
	
	//归并排序
	public static void MergeSort(int[] arr) {
		int[] arr2 = Divide(arr);
		for(int i=0;i<arr2.length;i++) {
			arr[i]=arr2[i];
		}
	}
	
	public static int[] Divide(int[] arr) {
		int pivot = (arr.length)/2;
		if(pivot>=1) {
			int[] left = new int[pivot];
			int[] right = new int[arr.length-pivot];
			for(int i=0;i<left.length;i++) {
				left[i] = arr[i];
			}
			for(int j=0;j<right.length;j++) {
				right[j]=arr[pivot+j];
			}
			
			left = Divide(left);
			right = Divide(right);
		
			return Conquer(left, right);
		}
		return arr;
	
	}
	
	
	public static int[] Conquer(int[] arr1, int[] arr2) {
		int[] temp = new int[arr1.length+arr2.length];
		int cur =0;
		int left =0;
		int right =0;
		while(true) {
			if(arr1[left]<arr2[right]) {
				temp[cur] = arr1[left];
				cur++;
				left++;
			}
			else if(arr1[left] > arr2[right]) {
				temp[cur] = arr2[right];
				cur++;
				right++;
			}
			else {
				temp[cur] =arr1[left];
				cur++;
				left++;
				temp[cur] = arr2[right];
				cur++;
				right++;
			}
			if(left>=arr1.length) {
				for(int i=right;i<arr2.length;i++) {
					temp[cur] = arr2[i];
					cur++;
				}
				break;
			}
			else if(right>=arr2.length){
				for(int i=left;i<arr1.length;i++) {
					temp[cur] = arr1[i];
					cur++;
				}
				break;
			}
		}
		
		return temp;
	}
	
	
	public static void RadixSort(int[] array) {
		//找出最大的一位
		int Max =0;
		for(int i=0;i<array.length;i++) {
			if(array[Max] <array[i]) {
				Max =i;
			}
		}
		
		//得出最大一位的个数
		int count=0;
		int temp =array[Max];
		while(temp>0) {
			temp /= 10;
			count++;
		}
		for(int j=0;j<count;j++) {
			busket(array, pow(10,j));
		}
		
		
	}
	
	//计算一个数的几次方
	public static int pow(int num, int exp) {
		if(exp==0) {
			return 1;
		}
		for(int i=0;i<exp-1;i++) {
			num *= num;
		}
		return num;
	}
	
	public static void busket(int[] array, int digit) {
		//创建一个桶用来记录数据
		int[][] bucket = new int[10][array.length];
		
		//创建一个数组来记录每个桶里面元素的个数
		int[] itemNum = new int[10];
		
		for(int i=0;i<array.length;i++) { 
		
			int no = array[i]/digit%10; //哪一个桶
			bucket[no][itemNum[no]] = array[i] +10;
			itemNum[no] +=1;
		}
		
		int index=0;
		for(int j=0;j<10;j++) {
			for(int k=0;k<bucket.length;k++) {
				if(bucket[j][k] !=0) {
					array[index] = bucket[j][k] -10;
					bucket[j][k] =0;
					index++;
				}
				else {
					break;
				}
			}
			itemNum[j] =0;
		}
		index =0;
		
		
	}
}

运行结果

在这里插入图片描述

参考资料

尚硅谷数据结构与算法:https://www.bilibili.com/video/BV1E4411H73v?p=56&spm_id_from=pageDriver

菜鸟教程:https://www.runoob.com/wp-content/uploads/2019/03/0B319B38-B70E-4118-B897-74EFA7E368F9.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值