一.桶排序
问题:期末考试班上五位同学分别考了5分,7分,3分,8分,1分,请问怎么将分数进行从大到小排序呢?
这个问题有多种解法,如果用桶排序的做法是这样的。
1.观察到这五个数为0-9之内的数,所以申请一个大小为10的数组 int a[10];
2.数组坐标为0-9,初始化为9,循环遍历五个数,当数组下标与分数相同时,即将数组值+1
3.循环遍历数组,遇到大于0的就输出。
代码如下:
import java.util.Scanner;
public class TongPaixu {
public static void main(String[] args) {
int[] a = new int[10];//创建一个数组
int t;
Scanner sc = new Scanner(System.in);
for(int i=0;i<10;i++){
a[i] = 0; //初始化为0
}
for(int i=0; i < 5; i++){//循环读入5个数,若读入的数和数组坐标一样,即把数组值加1
t = sc.nextInt();
a[t]++;
}
for(int i = 0; i < 10; i++){//循环遍历数组,一次判断a[0]到a[9]
for(int j=1; j<=a[i]; j++){ //出现几次就打印几次
System.out.print(i+" ");
}
}
sc.close();
}
}
简单来讲,桶排序就是准备若干个桶,此处要注意桶的编号范围一定要大于待排序的数的范围,读到哪个数,就将这个数扔进对应的桶里。该算法的时间复杂度是循环的桶的个数m加上排序的数n以及判断输出的m+n,即O(2*(m+n)), 忽略较小的常数,即时间复杂度为0(m+n).如果待排序的数范围较大,比如1001,944,299,333,384,121,那么就需要准备121-1001这么多个桶,浪费资源,所以,桶排序适合数范围较小的排序。
二,冒泡排序
问题:给定一串数,12,45,99,77,32,将其由小到大排序
将这五个数从小到大排序,可以先通过判断相邻两个数的大小,小的数在左边,大的数在右边,如果不是,则交换两个数的位置。第一轮过后,顺序是:12, 45,77,32,99,第二轮:12,45,32,77,99,第三轮:12,32,45,77,99,第四轮顺序维持不变,一般有n个数,需要排n-1轮。代码如下:
import java.util.Scanner;
public class MaoPaoPaixu {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] a = new int[11];
int temp;
int n = sc.nextInt();//n表示接下来有n个数
for(int i=1; i<=n; i++){ //循环读入n个数到数组
a[i] = sc.nextInt();
}
//冒泡排序核心算法
for(int i=1; i<n;i++){ //循环n-1轮
for(int j=1;j<=n-i; j++){ //每轮遍历数组,因为没进行一轮就会排好一个数到最后,所以
//不用每次扫描都末尾
if(a[j]>a[j+1]){//比较大小并交换
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
for(int i=1; i <=n; i++){//遍历输出排好序的数组
System.out.print(a[i]+" ");
}
sc.close();
}
}
冒泡排序的原理是每一趟只能将一个数归位,即第一趟只能确定将末位上的数归位,第二趟只能将倒数第二位上的数归位,以此类推。基本思想是每次比较相邻的两个元素,如果它们的顺序错误就把它们交换过来。其核心部分是两重嵌套循环,所以时间复杂度是O(N^2).
三.快速排序
问题:将下列一串数字按照从大到小排列,6,4,1,7,2,3,5,8,10,9
上面我们刚讲到冒泡排序,其做法是每一轮比较相邻两个数,算法的时间复杂度是比较高的,那么有没有更快的算法呢?有,那就是快速排序,名字上都体现出来了!!其基本思想是选定两个基本数,然后用两个变量i,j,分别先从右往左(j从右端开始)找一个比基准数大的数(本题是要求数字从大到小排列),在从左往右(i从左开始)找一个比基准数小的的数,然后就换他们,当i与j相遇时,即指向相同元素时,交换此元素与基准数,第一轮结束,接下来以基准数为分界点,拆分成左右两个序列,对两个子序列进行同样的处理。代码如下:(建议大家参考代码理解更加)
import java.util.Scanner;
public class KuaiSuPaixu {
static int n;
static int[] a = new int[100] ;
public static void quickSort(int left, int right){
int temp,t,i,j;
if(left > right)
return;
temp = a[left]; //temp存的数是基准数,这里我们选择
i= left; //最左端的数,其实可以任意
j = right;
while(i != j){
//顺序很重要,要先从右往左找
while(a[j] <= temp && i < j){
j--;
}
//在从左往右找
while(a[i] >= temp && i < j ){
i++;
}
//交换两个数在数组中的位置
if(i<j){
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//将基准位归位
a[left] = a[i];
a[i] = temp;
//子序列继续处理
quickSort(left, i-1);
quickSort(i+1, right);
return;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); //个数n
for(int i=1; i<=n; i++){ //读入n个待排序的数
a[i] = sc.nextInt();
}
quickSort(1,n);
//输出排序后的结果
for(int i=1; i<=n; i++){
System.out.print(a[i]+" ");
}
sc.close();
}
}
快速排序之所以比较快,是相比于冒泡排序的每次交换相邻两个数,快速排序可以跳跃式交换。快速排序的平均时间复杂度是O(NlogN)。最差排序时间是O(N^2),即当存在每次只能交换相邻两个数的时候(基本很少)。