算法之三种简单的排序

一.桶排序

问题:期末考试班上五位同学分别考了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),即当存在每次只能交换相邻两个数的时候(基本很少)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值