对于一个算法的性能来说,除了时间复杂度,还有空间复杂度,稳定性等一系列指标。我平常说的算法复杂度可分为两部分:时间复杂度和空间复杂度。
从这两个维度综合分析,可以知道一个算法的好坏,然后才可以针对这个算法进行优化。
桶排序也叫箱排序,它简单而快速。其中的主要思想是我们首先需要知道所有待排序元素的范围,然后需要有在这个范围内的同样数量的桶,接着把元素放入对应的桶,最后按顺序输出。
但是,当待排序元素很多大的时候,比如100万个,我们要设置100万个桶吗,当然不可能。在很多时候我们会把桶排序与其他排序相结合,一个桶里有多个元素,那这岂不是跟散列表很相似呢。
讲了这么多,是不是感觉很简单呢,跟我来实现一个简单的桶排序吧。
public class BubbleSort {
private int[] array;
public BubbleSort(int[] array) {
this.array = array;
}
/**
* 从小到大
*/
public void sort() {
int length = array.length;
if (length > 0) {
for (int i = 1; i < length; i++) {
for (int j = 0; j < length - i; j++) {
if (array[j] > array [j + 1 ]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
/**
* 从大到小
*/
public void sort2() {
int length = array.length;
if (length > 0) {
for (int i = length - 1; i > 0; i--) {
for (int j = length - 1; j > length - 1 -i; j--) {
if (array[j] > array [j - 1 ]) {
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
}
public void print() {
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
public static void testBucketSort() {
int[] array = {5, 9, 1, 9, 5, 8, 4, 3, 2, 9, 15, 7, 0};
BucketSort bucketSort = new BucketSort(16, array);
bucketSort.sort();
bucketSort.print();
}
进行桶排序的时候需要遍历一遍所有的待排序元素,然后依次放入指定位置。如果加上输出排序的时间,那么需要遍历所有的桶,时间复杂度就是O(n+m),其中n为待排序元素的个数,m为桶的个数,排序速度没毛病,可就是空间消耗来说太多了,特别是当元素跨度太大的时候,空间浪费就越多,元素分布得太分散,当这种情况的时候就不适合桶排序算法。
冒泡排序是我接触的第一个排序算法,那时候还是大一,在学C语言。冒泡排序也是一个比较简单的排序,它重复得走访要排序的数列,一次比较两个元素,如果顺序不对,则进行交换,一直重复这样的步骤,直到找到没有交换的元素为止。
首先,有一个数组,里面存储着待排序的元素,我们需要把元素从大到小排序,然后我们从尾部到头开始下面的步骤:
当然,我这里说的是从大到小排序,当需要从小到大排序的时候,从头部到尾部进行操作即可。
下面,我们一起来实现这个冒泡排序算法。
public class BubbleSort {
private int[] array;
public BubbleSort(int[] array) {
this.array = array;
}
/**
* 从小到大
*/
public void sort() {
int length = array.length;
if (length > 0) {
for (int i = 1; i < length; i++) {
for (int j = 0; j < length - i; j++) {
if (array[j] > array [j + 1 ]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
/**
* 从大到小
*/
public void sort2() {
int length = array.length;
if (length > 0) {
for (int i = length - 1; i > 0; i--) {
for (int j = length - 1; j > length - 1 -i; j--) {
if (array[j] > array [j - 1 ]) {
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
}
public void print() {
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
public static void testBubbleSort() {
int[] array = {5, 9, 1, 6, 5, 8, 4, 3, 2, 19, 15, 7, 0};
BubbleSort bubbleSort = new BubbleSort(array);
bubbleSort.sort2();
bubbleSort.print();
}
冒泡排序算法每轮排序使一个元素排到一端,最终进行n-1次这样的排序(n为待排序的数列的的长度),而在每轮排序中都需要对相邻的两个元素进行比较,最坏的情况下,每次比较都需要交换位置,所以这里的时间复杂度为O()。其实冒泡排序在最好的情况下,可以达到O(n),这当然是在待排序数列有序的情况下,但是这种情况很少,所以冒泡排序的平均时间复杂度为O()。
当然,冒泡排序还是可以优化的。
1. 增加标志位。增加一个标志位来标记每趟排序中最后一次交换的位置,由于这个元素之后的位置已经不用交换了,说明后面的元素都完成了排序,所以下次就可以直接从尾部比较到这个标记的元素。
2. 一次冒两个元素。每一趟排序都是把最大的元素冒上去,把最小的元素沉下去。排序次数可以减少一半。