9. 桶排序

思想

桶排序,也是爲了解決計數排序計數數組大小設置的問題。桶排序,就是把待排序數據分爲不同的區間,然後區間內進行排序,最後即可完成排序。

就有點像,成績會有一個區間,比如100-90, 90-80這樣,每個區間就是一個桶,然後對桶內元素進行排序。最後取出來,即完成排序。

從上面分析可以看出,我們對區間排序的時候,最好每個區間(桶)中數據是均勻的。

至於如何對桶內元素進行排序?這個是一個困惑,網上很多給的實例,是直接調用 api 的排序函數。

維基百科上,是對桶內數據採用插入排序的方法。

我個人偏向於第二種。

第一種有點投機取巧,雖然Java中的排序函數,會根據數據量的大小選用不同的排序函數,因爲不同的數據量,不同的排序函數的時間效率還是有點差別的。java中的排序函數應該會根據數據量大小,調用相對高效的排序函數。

這裏還得知道,在數據量較小的情況下,插入排序比快排和歸併要高效。因爲桶分數據,相對假設每個桶的數據都比較少,所以個人偏向桶內排序採用插入排序。

實現

貼出維基百科上的代碼

private int indexFor(int a, int min, int step) {
		return (a - min) / step;
	}

	public void bucketSort(int[] arr) {

		int max = arr[0], min = arr[0];
		for (int a : arr) {
			if (max < a)
				max = a;
			if (min > a)
				min = a;
		}
		// 該值也可根據實際情況選擇
		int bucketNum = max / 10 - min / 10 + 1;
		List buckList = new ArrayList<List<Integer>>();
		// create bucket
		for (int i = 1; i <= bucketNum; i++) {
			buckList.add(new ArrayList<Integer>());
		}
		// push into the bucket
		for (int i = 0; i < arr.length; i++) {
			int index = indexFor(arr[i], min, 10);
			((ArrayList<Integer>) buckList.get(index)).add(arr[i]);
		}
		ArrayList<Integer> bucket = null;
		int index = 0;
		for (int i = 0; i < bucketNum; i++) {
			bucket = (ArrayList<Integer>) buckList.get(i);
			insertSort(bucket);
			for (int k : bucket) {
				arr[index++] = k;
			}
		}

	}

	// 把桶內元素插入排序
	private void insertSort(List<Integer> bucket) {
		for (int i = 1; i < bucket.size(); i++) {
			int temp = bucket.get(i);
			int j = i - 1;
			for (; j >= 0 && bucket.get(j) > temp; j--) {
				bucket.set(j + 1, bucket.get(j));
			}
			bucket.set(j + 1, temp);
		}
	}

需要注意的是,桶的數據結構,是採用arraylist接arraylist。

下圖中是鏈表形式,所以我塗改了,應該是arraylist而不是鏈表。

複雜度

複雜度分析的話,主要是取決於每個桶中的時間複雜度。

如果桶爲很多,每個桶中只有一個數據,那麼其實就是計數排序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章