Rust에서의 정렬 방법은 Vec
항상 가장 작은 것부터 가장 큰 것까지 요소를 정렬합니다. 대신 가장 큰 것에서 가장 작은 것으로 정렬하는 범용 방법은 무엇입니까?
숫자 벡터가있는 경우 다음과 같이 숫자를 "반전"하는 키 추출 함수를 제공 할 수 있습니다.
let mut numbers: Vec<u32> = vec![100_000, 3, 6, 2];
numbers.sort_by_key(|n| std::u32::MAX - n);
그러나 그것은 그다지 명확하지 않으며 그 방법을 문자열과 같은 다른 유형으로 확장하는 것은 간단하지 않습니다.
이를 수행하는 방법은 최소한 세 가지가 있습니다.
vec.sort_by(|a, b| b.cmp(a))
이렇게하면 요소가 비교되는 순서가 전환되어 더 작은 요소가 정렬 기능에 더 크게 나타나고 그 반대의 경우도 마찬가지입니다.
use std::cmp::Reverse;
vec.sort_by_key(|w| Reverse(*w));
Reverse
Ord
래핑 된 유형의 순서와 반대 인 인스턴스를 가진 일반 래퍼입니다 .
Reverse
를 제거하여 포함 된 참조 를 반환하려고하면 *
내부에서 직접 참조를 반환 할 때와 마찬가지로 수명 문제가 발생합니다 sort_by_key
( 이 질문 참조 ). 따라서이 코드 조각은 키가 Copy
유형 인 벡터에만 사용할 수 있습니다.
vec.sort();
vec.reverse();
처음에는 잘못된 순서로 정렬 한 다음 모든 요소를 반대로합니다.
criterion
길이 100_000에 대해 세 가지 방법을 벤치마킹했습니다 Vec<u64>
. 타이밍 결과는 위의 순서로 나열됩니다. 왼쪽 값과 오른쪽 값은 각각 신뢰 구간의 하한과 상한을 표시하고 중간 값은 criterion
의 최선의 추정치입니다.
성능은 비슷하지만 반전 된 비교 기능은 약간 느립니다.
Sorting/sort_1 time: [6.2189 ms 6.2539 ms 6.2936 ms]
Sorting/sort_2 time: [6.1828 ms 6.1848 ms 6.1870 ms]
Sorting/sort_3 time: [6.2090 ms 6.2112 ms 6.2138 ms]
로 다음 파일 저장, 재생하는 방법 benches/sort.rs
과 Cargo.toml
, 다음 실행합니다 cargo bench
. 벡터 복제 비용이 정렬과 관련이 없는지 확인하는 추가 벤치 마크가 있으며 몇 마이크로 초 만 소요됩니다.
fn generate_shuffled_data() -> Vec<u64> {
use rand::Rng;
let mut rng = rand::thread_rng();
(0..100000).map(|_| rng.gen::<u64>()).collect()
}
pub fn no_sort<T: Ord>(vec: Vec<T>) -> Vec<T> {
vec
}
pub fn sort_1<T: Ord>(mut vec: Vec<T>) -> Vec<T> {
vec.sort_by(|a, b| b.cmp(a));
vec
}
pub fn sort_2<T: Ord + Copy>(mut vec: Vec<T>) -> Vec<T> {
vec.sort_by_key(|&w| std::cmp::Reverse(w));
vec
}
pub fn sort_3<T: Ord>(mut vec: Vec<T>) -> Vec<T> {
vec.sort();
vec.reverse();
vec
}
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn comparison_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("Sorting");
let data = generate_shuffled_data();
group.bench_function("no_sort", |b| {
b.iter(|| black_box(no_sort(data.clone())))
});
group.bench_function("sort_1", |b| {
b.iter(|| black_box(sort_1(data.clone())))
});
group.bench_function("sort_2", |b| {
b.iter(|| black_box(sort_2(data.clone())))
});
group.bench_function("sort_3", |b| {
b.iter(|| black_box(sort_3(data.clone())))
});
group.finish()
}
criterion_group!(benches, comparison_benchmark);
criterion_main!(benches);
[package]
name = "sorting_bench"
version = "0.1.0"
authors = ["nnnmmm"]
edition = "2018"
[[bench]]
name = "sort"
harness = false
[dev-dependencies]
criterion = "0.3"
rand = "0.7.3"
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다