桶排序

首先讨论的问题:给定一个数组,求如果排序后,相邻两数的最大值,要求时间复杂度 O(n)?

:数组长度N,设计一个桶,数量为(N+1)个桶,数组最小值放进第一个桶,数组最大值放进最后一个桶,每一个桶都要包含minmax,这两个边界值。所以中间一定存在一个空桶,那么就可以得到一个结论:桶内之间绝对不会存在最大差值,最大差值就一定在桶与桶的边界值之间。从第二个桶开始遍历,用这个桶的min减去前一个非空桶max得到差值,那么整个数组相邻的最大差值一定在这里面。

#include <stdio.h>
 
//根据要入桶的数和最大最小值得到对应桶编号
int getBucketId(int num,int bucketsNum,int min,int max){
    return (num - min) * bucketsNum / (max - min);
}
 
int max(int a, int b){
    return a > b ? a : b;
}
 
int min(int a, int b){
    return a < b ? a : b;
}
 
int getMaxGap(int arr[], int length) {
    if (arr == NULL || length < 2) {
        return -1;
    }
    int maxValue = -999999, minValue = 999999;
    int i;
    //找出最大最小值
    for (i = 0; i < length; ++i) {
        maxValue = max(maxValue, arr[i]);
        minValue = min(minValue, arr[i]);
    }
    //记录每个桶的最大最小值以及是否有数,初始时每个桶都没数
    int maxs[length + 1], mins[length + 1];
    bool hasNum[length + 1];
    for (i = 0; i < length + 1; i++) {   
        hasNum[i] = false;
    }
    //put maxValue into the last bucket
    mins[length] = maxs[length] = maxValue;
    hasNum[length] = true;
 
    //iterate the arr
    int bid; //bucket id
    for (i = 0; i < length; i++) {
        if (arr[i] != maxValue) {
            bid = getBucketId(arr[i], length + 1, minValue, maxValue);
              //如果桶里没数,则该数入桶后,最大最小值都是它,否则更新最大最小值
            mins[bid] = !hasNum[bid] ? arr[i] : arr[i] < mins[bid] ? arr[i] : mins[bid];
            maxs[bid] = !hasNum[bid] ? arr[i] : arr[i] > maxs[bid] ? arr[i] : maxs[bid];
            hasNum[bid] = true;
        }
    }
 
    //find the max gap between two nonEmpty buckets
    int res = 0, j = 0;
    for (i = 0; i < length; ++i) {
        j = i + 1;//the next nonEmtpy bucket id
        while (!hasNum[j]) {//the last bucket must has number
            j++;
        }
        res = max(res, (mins[j] - maxs[i]));
    }
 
    return res;
}
 
int main(){
    int arr[] = {13, 41, 67, 26, 55, 99, 2, 82, 39, 100};
    printf("%d", getMaxGap(arr, 9));    //17
    return 0;
}

理解了上述代码的话,桶排序就很简单了,就是计数排序,统计一个数出现了多少次,然后重新打印会数组。但是局限于要排序的数组max值很小。否则数组开销代价太大。桶排序是非比较的,是统计的。

package 左神_算法;
import java.util.Arrays;

public class BucketSort {
	/**
	 * 桶排序
	 * 1,非基于比较的排序,与被排序的样本的实际数据状况很有关系,所
	  	以实际中并不经常使用
	 * 2,时间复杂度O(N),额外空间复杂度O(N)
	 * 3,稳定的排序
	 *
	 */
	 
		// only for 0~200 value,计数排序
		public static void bucketSort(int[] arr) {
			if (arr == null || arr.length < 2) {
				return;
			}
			int max = Integer.MIN_VALUE;
			for (int i = 0; i < arr.length; i++) {
				max = Math.max(max, arr[i]);   
			}
			int[] bucket = new int[max + 1];  // 定义一个可以容纳数组里面的max+1个数
			for (int i = 0; i < arr.length; i++) {  // 把arr的值映射进数组里面,记录有多少个
				bucket[arr[i]]++;
			}
			int i = 0;
			for (int j = 0; j < bucket.length; j++) {  //把桶里面的值,重新输入到arr中
				while (bucket[j]-- > 0) {
					arr[i++] = j;
				}
			}
		}
	 
		// for test
		public static void comparator(int[] arr) {
			Arrays.sort(arr);
		}
	 
		// for test
		public static int[] generateRandomArray(int maxSize, int maxValue) {
			int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
			for (int i = 0; i < arr.length; i++) {
				arr[i] = (int) ((maxValue + 1) * Math.random());
			}
			return arr;
		}
	 
		// for test
		public static int[] copyArray(int[] arr) {
			if (arr == null) {
				return null;
			}
			int[] res = new int[arr.length];
			for (int i = 0; i < arr.length; i++) {
				res[i] = arr[i];
			}
			return res;
		}
	 
		// for test
		public static boolean isEqual(int[] arr1, int[] arr2) {
			if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
				return false;
			}
			if (arr1 == null && arr2 == null) {
				return true;
			}
			if (arr1.length != arr2.length) {
				return false;
			}
			for (int i = 0; i < arr1.length; i++) {
				if (arr1[i] != arr2[i]) {
					return false;
				}
			}
			return true;
		}
	 
		// for test
		public static void printArray(int[] arr) {
			if (arr == null) {
				return;
			}
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i] + " ");
			}
			System.out.println();
		}
	 
		// for test
		public static void main(String[] args) {
			int testTime = 500000;
			int maxSize = 100;
			int maxValue = 150;
			boolean succeed = true;
			for (int i = 0; i < testTime; i++) {
				int[] arr1 = generateRandomArray(maxSize, maxValue);
				int[] arr2 = copyArray(arr1);
				bucketSort(arr1);
				comparator(arr2);
				if (!isEqual(arr1, arr2)) {
					succeed = false;
					printArray(arr1);
					printArray(arr2);
					break;
				}
			}
			System.out.println(succeed ? "Nice!" : "Fucking fucked!");
	 
			int[] arr = generateRandomArray(maxSize, maxValue);
			printArray(arr);
			bucketSort(arr);
			printArray(arr);
	 
		}
	

}
原文地址:https://www.cnblogs.com/horken/p/10706136.html