浅谈桶排序思想(附源码)

引子

最近被人问了冒泡排序,解释了半天没听懂。可以理解,毕竟冒泡的原理是较为繁琐的。于是我决定将一种非常简单,稳定的排序算法教给大家。

原理

我们打个比方:现有N张卡片,每张卡片上都写有数字(1\leqslant数字\leqslantM)。现将这些卡片打乱,求:将卡片从小到大依次排列。

解决方案

准备M个桶,并给每个桶编上编号(即第一个桶为1号,第二个桶为2号,......,第M个桶为M号)。然后从头到尾一张一张的将卡片放入对应的桶(即若卡片上写有数字为10,则将卡片放入10号桶,其他以此类推)。然后从第一个桶开始检查:若桶里有卡片,则把卡片拿起来,接着检查第二个桶......于是,当你检查完所有的桶后,你手上的卡片就是有序的了。

没错,就这样,很有趣,对吧?

如果你在反复阅读下已经深谙其理,那么请向下读

理论存在,实践开始

测试题目:U192825 排卡片 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

需要解决的问题

  • 桶怎么解决(如何创造桶):在很多编程语言当中,有“数组”这一概念————没错,用数组来模拟一个个桶,这样就免去了桶的编号
  • 为什么要创造M个桶:好问题!我们知道,要将对应的卡片放入对应的桶中,那么桶的数量直接与卡片相关,即卡片上数字的最大限度相关,毕竟桶给多了也没用,桶给少了卡片就找不到对应的桶。而上文已明确指出:卡片上的数字最大为M,所以我们要创建M个桶

实践

C语言

#include<stdio.h>
#define M 1000

unsigned long arr[M+10] = {0};		//桶,为防止内存溢出,多开几个,问题不大 
unsigned long n = 0;

main()
{
	scanf("%d",&n);
	int tmp = 0;
	int i;
	for(i=1;i<=n;i++){ 
		scanf("%d",&tmp);	//逐个输入
		arr[tmp]++; 		//将卡片放入桶内 
	}
	for(i=1;i<=M;i++){
		while(arr[i]!=0){
			printf("%d ",i);//只要里面还有卡片,就重复输出 
			arr[i]--;		//别忘了要把卡片拿出来 
		}
	} 
	return 0;
}

C++

#include<iostream>
#define M 1000

using namespace std;

unsigned long arr[M+10] = {0};		//桶,为防止内存溢出,多开几个,问题不大 
unsigned long n = 0;

main()
{
	cin>>n;
	int tmp = 0;
	for(int i=1;i<=n;i++){ 
		cin>>tmp;			//逐个输入
		arr[tmp]++; 		//将卡片放入桶内 
	}
	for(int i=1;i<=M;i++){
		while(arr[i]!=0){
			cout<<i<<" ";	//只要里面还有卡片,就重复输出 
			arr[i]--;		//别忘了要把卡片拿出来 
		}
	} 
	return 0;
}

Java

import java.io.*;
import java.util.Scanner;
public class Main {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		long arr[] = new long[1005];
		int n;
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		int tmp;
		for(int i=1;i<=n;i++) {
			tmp = scanner.nextInt();
			arr[tmp]++;
		}
		for(int i=1;i<=1000;i++) {
			while(arr[i]!=0) {
				System.out.print(i+" ");
				arr[i]--;
			}
		}
	}

}

这样看,桶排序只需循环M遍,而若采用冒泡排序却需要N^{2}遍,而在此题中,桶排序只需循环1000遍,而冒泡排序却需循环100000^{2}=1\times 10^{10}遍,很明显会超时。相信你也已然体验到桶排序的强大了吧!

(本文完)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值