Держите по одному текущему значению каждого канала, выдавайте минимальное и обновляйте только его источник. Для правильного порядка нужна голова каждого ещё открытого потока.
Написать функцию merge для слияния нескольких отсортированных каналов uint в один отсортированный канал
Держите по одному текущему значению каждого канала, выдавайте минимальное и обновляйте только его источник. Для правильного порядка нужна голова каждого ещё открытого потока.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Держите по одному текущему значению каждого канала, выдавайте минимальное и обновляйте только его источник. Для правильного порядка нужна голова каждого ещё открытого потока.
Простой вариант на Go с отменой (нужен import "context"):
func merge(ctx context.Context, inputs ...<-chan uint) <-chan uint {
out := make(chan uint)
go func() {
defer close(out)
heads := make([]uint, len(inputs))
active := make([]bool, len(inputs))
for i, ch := range inputs {
select {
case heads[i], active[i] = <-ch:
case <-ctx.Done(): return
}
}
for {
best := -1
for i := range inputs {
if active[i] && (best < 0 || heads[i] < heads[best]) {
best = i
}
}
if best < 0 { return }
select {
case out <- heads[best]:
case <-ctx.Done(): return
}
select {
case heads[best], active[best] = <-inputs[best]:
case <-ctx.Done(): return
}
}
}()
return out
}
Входы отсортированы и закрываются производителями. Ноль — обычное значение, конец определяется ok. Время O(Nk), память O(k); min-heap уменьшит выбор минимума до O(log k). Медленный источник может задержать весь merge. Производители тоже должны учитывать общий context, иначе отмена merge не остановит их отправки.