原理讲解:
Kogge-Stone 是一种并行前缀和算法。与线性扫描(从左到右依次累加)不同,它通过多轮迭代让每个位置"同时"向前收集信息。
| 轮次 | 规则 | 效果 |
|---|---|---|
| 第1轮 | 每个人看向左边第1个人,把对方的数加到自己手里 | 每人手里是 2人 的和 |
| 第2轮 | 每个人看向左边第2个人,把对方的数加到自己手里 | 每人手里是 4人 的和 |
| 第3轮 | 每个人看向左边第4个人,把对方的数加到自己手里 | 每人手里是 8人 的和 |
| ... | 距离每轮翻倍 | ... |
经过 log₂(n) 轮后,每个人手里就是从队首到自己位置所有人的总和。
中文伪代码:
bash
算法 Kogge-Stone-前缀和(数组 A, 长度 n)
如果 n <= 1
返回
// 初始化双缓冲
源数组 S ← A 的副本
目标数组 D ← 长度为 n 的新数组
步长 step ← 1
当 step < n 时循环
对于 i 从 0 到 n-1 循环
如果 i < step
D[i] ← S[i] // 左边不够 step 个,保持原值
否则
D[i] ← S[i] + S[i - step] // 加上左边第 step 个位置的值
结束如果
结束循环
交换(S, D) // 下一轮以本轮结果作为输入
step ← step × 2
结束循环
// 最后结果在 S 中(交换次数决定)
A ← S
结束算法
Rust代码实现:
rust
use std::io;
fn main() {
let mut input = String::new();
println!("请输入用空格分隔的整数序列:");
io::stdin()
.read_line(&mut input)
.expect("读取输入失败");
let mut nums: Vec<i64> = input
.split_whitespace()
.filter_map(|s| s.parse().ok())
.collect();
if nums.is_empty() {
println!("没有输入数字。");
return;
}
kogge_stone_prefix_sum(&mut nums);
println!("前缀和结果:{:?}", nums);
}
fn kogge_stone_prefix_sum(nums: &mut [i64]) {
let n = nums.len();
if n <= 1 {
return;
}
// 双缓冲:交替读写,避免每轮全量拷贝
let mut src = nums.to_vec();
let mut dst = vec![0i64; n];
let mut step = 1;
while step < n {
for i in 0..n {
if i < step {
dst[i] = src[i]; // 距离不够,保持原值
} else {
dst[i] = src[i] + src[i - step]; // Kogge-Stone 核心
}
}
std::mem::swap(&mut src, &mut dst);
step <<= 1;
}
// 最后一轮结果在 src 中(因为 swap 了奇数次/偶数次)
nums.copy_from_slice(&src);
}
步骤:
