排序算法讲解(1) - 桶排+冒泡
桶排
思想:
这可以说是最快的排序,有种哈希的感觉,要在被排序数组比较均匀的分布在一个区间的时候使用,思路就是用一个数组记录被排序元素中每一个数字数字的出现次数然后,更具这个数组得到排序后的数组
具体实现
import java.util.Arrays;
import java.util.Random;
public class BucketSort {
public void sort(int[] nums){
if(nums==null || nums.length == 0){
return;
}
int max = Arrays.stream(nums).max().getAsInt(); // 根据数组的最大值构造桶
int min = Arrays.stream(nums).min().getAsInt();
int len = max-min+1;
int[] buckets = new int[len];
for (int num : nums) { // 记录每一个数出现的次数
buckets[num-min]++;
}
int cur = 0;
for (int i = 0; i < len; i++) {
while (buckets[i] -- >0){
nums[cur] = i+min;
cur++;
}
}
}
public static void main(String[] args) {
int[] test = new Random().ints(-10, 10).limit(100).toArray();
Arrays.stream(test).peek(x-> System.out.print(x+" ")).toArray();
System.out.println();
new BucketSort().sort(test);
Arrays.stream(test).peek(x-> System.out.print(x+" ")).toArray();
}
}
分析:
时间复杂度为O(n)
空间复杂度均为O(m),m为数组区间长度
上述的代码用数组去模拟桶的实现,但是如果用链表模拟的时候,桶排是一种稳定排序.
冒泡排序
思想:
冒泡排序的基本思想是通过迭代比较,相邻之间的元素不断比较,将最大的元素一步步送到正确的位置
原数组:5 1 3 4 6 9 7 1
第一次:1 5 3 4 6 9 7 1
1 3 5 4 6 9 7 1
1 3 4 5 6 9 7 1
1 3 4 5 6 7 9 1
1 3 4 5 6 7 1 9
// 迭代比较相邻的数字,逆序则交换,将9送到了正确的位置
第二次:1 3 4 5 6 1 7 9
// 将7送到了正确的位置
第三次:1 3 4 5 1 6 7 9
// 将6送到了正确的位置
第四次:1 3 4 1 5 6 7 9
// 将5送到了正确的位置
第五次:1 3 1 4 5 6 7 9
// 将4送到了正确的位置
第六次:1 1 3 4 5 6 7 9
// 将三送到了正确的位置
第七次:1 1 3 4 5 6 7 9
// 排序完成
具体实现
import java.util.Arrays;
import java.util.Random;
public class PopSort {
public void sort(int[] nums){
if(nums == null || nums.length == 0 ){
return;
}
int len = nums.length;
for (int i = 0; i < len-1; i++) { //每一次循环将最大的数送到正确的位置
for (int j = 0; j < len-i-1; j++) { //当len-1个数的位置都正确,剩下的一个数字位置肯定也是正确的,所以只要len-1趟
if(nums[j+1] < nums[j]){ //比较,逆序则交换,一步步将最大的数字"运"到正确的位置
int temp = nums[j]; // len-i-1指的是未排序的数
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
}
public static void main(String[] args) {
// 生成一个随机数组
int[] test = new Random().ints(-100, 100).limit(10).toArray();
Arrays.stream(test).peek(x-> System.out.print(x+" ")).toArray();
System.out.println();
new PopSort().sort(test);
Arrays.stream(test).peek(x-> System.out.print(x+" ")).toArray();
}
}
分析
两个循环,时间复杂度是O(n^2),空间复杂度是O(1)
排序过程中,假设nums[i] = nums[j] ,且i<j , 排序后两个数的为num[k] 和 num [l],因为当num[i]<num[j]时才触发交换,所以i<j , k<l , 所以冒泡排序是稳定排序