其中:
思路:
算法描述:
动图演示:
代码演示:
// 默认升序排列
public int[] bubbleSort(int[] nums){
int len = nums.length;
for(int i = 0; i < len; i++){
for(int j = 0; j < len - i - 1; j++){
if(nums[j] > nums[j + 1]){
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
}
}
}
return nums;
}
// 默认升序排列
public int[] selectionSort(int[] nums){
int len = nums.length;
for(int i = 0; i < len - 1; i++){
// 从i开始向后找最小的元素
int minIndex = i;
for(int j = i; j <len; j++){
if(nums[minIndex] > nums[j]){
minIndex = j;
}
}
if(minIndex != i){
int tmp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = tmp;
}
}
return nums;
}
// 默认升序排列
public int[] insertionSort(int[] nums){
int len = nums.length;
for(int i = 1; i < len; i++){
// i之前是有序列表,i之后是无序列表
int tmp = nums[i];
// 在有序列表中从后向前扫描,找到适合tmp的位置,tmp之后的位置向后移动
for(int j = i - 1; j >= 0 && nums[j] > tmp; j--){
// 比tmp大的元素向后移动一位
nums[j + 1] = nums[j];
}
// 找到放tmp的位置
nums[j + 1] = tmp;
}
return nums;
}
// 默认升序排列
public int[] shellSort(int[] nums){
int len = nums.length;
for(int d = len / 2; d >= 0; d /= 2){
// d用于控制分组
// 对每个分组分别进行插入排序
for(int i = d; i < len; i += d){
int tmp = nums[i];
for(int j = i - d; j >= 0 && nums[j] > tmp; j -= d){
nums[j + d] = nums[j];
}
nums[j + d] = tmp;
}
}
return nums;
}
// 默认升序排列
// 用于存储排序的中间结果
int[] temp;
public int[] mergeSort(int[] nums){
int len = nums.length;
// 初始化temp
temp = new int[len];
mergeSort(nums, 0, len - 1);
return nums;
}
public void mergeSort(int[] nums, int left, int right){
if(left >= right){
return;
}
int mid = (left + right) / 2;
// 递归分治排序
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
// 合并排序的中间结果
merge(nums, left, mid + 1, right);
}
public void merge(int[] nums, int i, int j, int k){
// temp记录中间结果
for(int index = i; index <= k; index++){
temp[index] = nums[index];
}
// 合并结果
int index = i, mid = j - 1;
while(i <= mid && j <= k){
if(temp[i] > temp[j]){
nums[index++] = temp[j++];
} else {
nums[index++] = temp[i++];
}
}
// i或者j还有剩
while(i <= mid){
nums[index++] = temp[i++];
}
while(j <= k){
nums[index++] = temp[j++];
}
}
// 默认升序排列
public int[] quickSort(int[] nums){
int len = nums.length;
quickSort(nums, 0, len - 1);
return nums;
}
public void quickSort(int[] nums, int left, int right){
if(left >= right){
return;
}
// 以left位置的元素为基准
int tmp = nums[left];
int i = left, j = right;
while(i < j){
// j往左找到第一个小于tmp的数,将该数放到left的位置
while(i < j && nums[j] >= tmp){
j--;
}
nums[i] = nums[j];
// i往右找到第一个大于tmp的数,将该数放到right的位置
while(i < j && nums[i] <= tmp){
i++;
}
nums[j] = nums[i];
}
// i和j重合的位置,放置temp
// temp左侧都是小于于temp的数,temp右侧都是大于temp的数
nums[i] = tmp;
quickSort(nums, left, i);
quickSort(nums, i + 1, right);
}
// 默认升序排列
// 升序用大顶堆,降序用小顶堆
public int[] heapSort(int[] nums){
int len = nums.length;
// 构建大顶堆
buildHeap(nums, len);
// 交换大顶堆的堆顶元素和堆底元素,再调整大顶堆,循环往复
for(int i = len - 1; i >= len / 2; i--){
swap(nums, i, 0);
len--;
maxifyHeap(nums, 0, len);
}
return nums;
}
public void buildHeap(int[] nums, int len){
for(int i = len / 2; i >= 0; i--){
maxifyHeap(nums, i, len);
}
}
public void maxifyHeap(int[] nums, int parent, int len){
int left = 2 * parent + 1, right = left + 1, largest = parent;
if(left < len && nums[left] > nums[largest]){
largest = left;
}
if(right < len && nums[right] > nums[largest]){
largest = right;
}
if(largest != parent){
swap(nums, largest, parent);
maxifyHeap(nums, largest, len);
}
}
public void swap(int[] nums, int index1, int index2){
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}
public int[] countingSort(int[] nums){
// 统计序列的最大值和最小值
int min = nums[0], max = nums[0], len = nums.length;
for(int num : nums){
min = Math.min(min, num );
max = Math.max(max, num );
}
// 根据最大值和最小值构造新数组
int newLen = max - min + 1;
int[] countArray = new int[newLen];
// 统计nums中的元素出现频率
for(int num : nums){
countArray[num - min]++;
}
// 循环每一个元素,根据出现的次数,放入新的数组
int[] res = new int[len];
int index = 0;
for(int i = 0; i < newLen; i++){
for(int j = 0; j < countArray[i]; j++){
res[index++] = i + min;
}
}
return res;
}
public List<Integer> bucketSort(List<Integer> list){
// 统计序列的最大值和最小值
int max = list.get(0), min = list.get(0);
for (Integer value : list) {
max = Math.max(max, value);
min = Math.min(min, value);
}
// 确定桶的数量,创建桶
int bucketNum = (max - min) / list.size() + 1;
List<List<Integer>> buckets = new ArrayList<>(bucketNum);
for (int i = 0; i < bucketNum; i++) {
buckets.add(new ArrayList<>());
}
// 将待排序元素放入桶中
for (int i = 0; i < list.size(); i++) {
int index = (list.get(i) - min) / list.size();
buckets.get(index).add(list.get(i));
}
// 对每个桶内的元素进行排序 -- 这里采用快速排序
for (List<Integer> bucket : buckets) {
quickSort(bucket);
}
// 将桶排序结果进行合并
return buckets.stream().flatMap(Collection::parallelStream).collect(Collectors.toList());
}
public List<Integer> radixSort(List<Integer> list){
// 先确定最大的位数
int digit = getMaxDigit(list);
// 对每个位数进行同桶排序
for(int i = 0; i < digit; i++){
list = bucketSort(list, i);
}
return list;
}
public int getMaxDigit(List<Integer> list){
int digit = 1, base = 10;
for(int value : list){
while(value > base){
digit++;
base *= 10;
}
}
return digit;
}
public List<Integer> bucketSort(List<Integer> list, int digit){
int base = (int)Math.pow(10, digit);
// 初始化桶
List<List<Integer>> buckets = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
buckets.add(new ArrayList<>());
}
// 将元素放入桶中
for(int val : list){
int index = (val / base) % 10;
buckets.get(index).add(val);
}
// 合并桶内的元素
return buckets.stream().flatMap(Collection::parallelStream).collect(Collectors.toList());
}
三种排序算法都用到了桶排序,但是对于桶的使用方法不同: