洛谷P1177【模板】排序:十种排序算法全解(1)
扯谈
之前我已经把十大排序算法全讲了一遍(具体详见专栏C++排序算法),今天我们来用一道简单的题目总结实战一下。
算法实现
一、桶排序(Bucket Sort)
适用场景:数据范围已知且较小(需根据测试数据调整偏移量)
// Java
import java.io.*;
public class Main {static final int OFFSET = 100000;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine());int[] cnt = new int[200001];String[] strs = br.readLine().split(" ");for (int i = 0; i < n; i++) cnt[Integer.parseInt(strs[i]) + OFFSET]++;StringBuilder sb = new StringBuilder();for (int i = 0; i <= 200000; i++) while (cnt[i]-- > 0) sb.append(i - OFFSET).append(" ");System.out.println(sb);}
}
# Python
n = int(input())
nums = list(map(int, input().split()))
offset = 10**5
cnt = [0] * (2*10**5 +1)
for num in nums:cnt[num + offset] +=1
res = []
for i in range(len(cnt)):while cnt[i] >0:res.append(str(i - offset))cnt[i] -=1
print(' '.join(res))
// C
#include <stdio.h>
#define OFFSET 100000
int cnt[200001];
int main() {int n, x;scanf("%d", &n);for(int i=0; i<n; ++i) {scanf("%d", &x);cnt[x + OFFSET]++;}for(int i=0; i<=200000; ++i)while(cnt[i]--) printf("%d ", i - OFFSET);return 0;
}
// C++
#include <iostream>
using namespace std;
const int OFFSET = 1e5;
int cnt[200001];
int main() {ios::sync_with_stdio(false);int n, x;cin >> n;for(int i=0; i<n; ++i) {cin >> x;cnt[x + OFFSET]++;}for(int i=0; i<=200000; ++i)while(cnt[i]--) cout << i - OFFSET << " ";return 0;
}
二、基数排序(Radix Sort)
支持正负数处理
// Java
import java.io.*;
public class Main {static final int RADIX = 10;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine());String[] strs = br.readLine().split(" ");int[] arr = new int[n];for (int i = 0; i < n; i++) arr[i] = Integer.parseInt(strs[i]);// 分离正负数int posCount = 0;for (int num : arr) if (num >= 0) posCount++;int[] negs = new int[n - posCount];int[] poss = new int[posCount];int ni = 0, pi = 0;for (int num : arr) {if (num < 0) negs[ni++] = -num;else poss[pi++] = num;}// 排序负数if (negs.length > 0) radixSort(negs);// 排序正数if (poss.length > 0) radixSort(poss);// 合并结果StringBuilder sb = new StringBuilder();for (int i = negs.length - 1; i >= 0; i--) sb.append(-negs[i]).append(" ");for (int num : poss) sb.append(num).append(" ");System.out.println(sb);}static void radixSort(int[] arr) {int max = 0;for (int num : arr) if (num > max) max = num;for (exp = 1; max / exp > 0; exp *= 10) countingSort(arr, exp);}static void countingSort(int[] arr, int exp) {int[] output = new int[arr.length];int[] count = new int[RADIX];for (int num : arr) count[(num / exp) % RADIX]++;for (int i = 1; i < RADIX; i++) count[i] += count[i - 1];for (int i = arr.length - 1; i >= 0; i--) {int digit = (arr[i] / exp) % RADIX;output[--count[digit]] = arr[i];}System.arraycopy(output, 0, arr, 0, arr.length);}
}
# Python
def radix_sort(arr):if not arr:return []max_num = max(map(abs, arr))exp = 1while max_num // exp > 0:counting_sort(arr, exp)exp *= 10return arrdef counting_sort(arr, exp):output = [0] * len(arr)count = [0] * 19 # 处理负数偏移for num in arr:index = (num // exp) % 10 + 9count[index] += 1for i in range(1, 19):count[i] += count[i - 1]for i in range(len(arr)-1, -1, -1):index = (arr[i] // exp) % 10 + 9output[count[index]-1] = arr[i]count[index] -= 1arr[:] = outputn = int(input())
arr = list(map(int, input().split()))
neg = [x for x in arr if x < 0]
pos = [x for x in arr if x >= 0]
radix_sort(neg)
radix_sort(pos)
neg = [-x for x in reversed(neg)]
print(' '.join(map(str, neg + pos)))
// C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RADIX 10void counting_sort(int arr[], int n, int exp) {int* output = (int*)malloc(n * sizeof(int));int count[19] = {0}; // 处理负数偏移for (int i = 0; i < n; i++) {int digit = (arr[i] / exp) % RADIX + 9;count[digit]++;}for (int i = 1; i < 19; i++) count[i] += count[i-1];for (int i = n-1; i >= 0; i--) {int digit = (arr[i] / exp) % RADIX + 9;output[--count[digit]] = arr[i];}memcpy(arr, output, n * sizeof(int));free(output);
}void radix_sort(int arr[], int n) {if (n == 0) return;int max_val = 0;for (int i = 0; i < n; i++) {int abs_val = abs(arr[i]);if (abs_val > max_val) max_val = abs_val;}for (int exp = 1; max_val/exp > 0; exp *= 10)counting_sort(arr, n, exp);
}int main() {int n;scanf("%d", &n);int* arr = malloc(n * sizeof(int));for (int i = 0; i < n; i++) scanf("%d", &arr[i]);// 分离正负数int neg_count = 0;for (int i = 0; i < n; i++) if (arr[i] < 0) neg_count++;int* negs = malloc(neg_count * sizeof(int));int* poss = malloc((n - neg_count) * sizeof(int));int ni = 0, pi = 0;for (int i = 0; i < n; i++) {if (arr[i] < 0) negs[ni++] = -arr[i];else poss[pi++] = arr[i];}radix_sort(negs, neg_count);radix_sort(poss, n - neg_count);// 合并结果for (int i = neg_count-1; i >= 0; i--) printf("%d ", -negs[i]);for (int i = 0; i < n - neg_count; i++) printf("%d ", poss[i]);return 0;
}
// C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;void counting_sort(vector<int>& arr, int exp) {vector<int> output(arr.size());int count[19] = {0}; // 负数偏移处理for (int num : arr) count[(num / exp) % 10 + 9]++;for (int i = 1; i < 19; i++) count[i] += count[i-1];for (int i = arr.size()-1; i >= 0; i--) {int digit = (arr[i] / exp) % 10 + 9;output[--count[digit]] = arr[i];}arr = output;
}void radix_sort(vector<int>& arr) {if (arr.empty()) return;int max_val = 0;for (int num : arr) max_val = max(max_val, abs(num));for (int exp = 1; max_val/exp > 0; exp *= 10)counting_sort(arr, exp);
}int main() {ios::sync_with_stdio(false);int n; cin >> n;vector<int> arr(n), negs, poss;for (int i = 0; i < n; i++) {cin >> arr[i];if (arr[i] < 0) negs.push_back(-arr[i]);else poss.push_back(arr[i]);}radix_sort(negs);radix_sort(poss);reverse(negs.begin(), negs.end());for (int num : negs) cout << -num << " ";for (int num : poss) cout << num << " ";return 0;
}
由于篇幅限制,剩余请详见洛谷P1177【模板】排序:十种排序算法全解(2),求关