# go merge ordered queues

### Ordered queue merge

#### subject

One of the interview questions is very good. I didn't answer them well when I did it. I'll summarize afterwards.

golang can merge any number of ordered arrays. The function prototype is as follows:

``````func Sort(ctx context.Context, out chan<- int, in ... <-chan int)
``````

The ordered sequence is input by any number of chan, so it may increase at any time. The output is obtained by out chan

#### Analysis

There are similar problems in leetcode, and the ideas are relatively simple. The difficulty of this problem is how to access the chan element, once it is taken out, it is not easy to put it back.

At that time, slicing was considered as buf, and the number traversed from chan was first put into slicing, and then traversed slicing to find the minimum number. The problem of slicing is that it is not easy to judge whether a number is taken out or put back. The next time you traverse chan, it's not easy to determine which slice has the returned value.

Then I will think of using chan as buf, using buf with length of 1. When it is full, it means there is still value, and when it is empty, it means supplement value.

So the idea is as follows: create a group of chan with length of 1 as buf, store the value from out chan to buf chan in each cycle, and then traverse buf chan to find the minimum value. After each comparison, put the larger value back to the original position of buf chan.

#### code implementation

The buf structure is defined as follows. Tmp is chan of length 1. The extracted elements are compared with Curr

``````type Head struct {
Curr int
Tmp chan int
}
``````

There are still some details to deal with;

• You need to use ctx.Done() to exit
• When reading in value from in, you need to judge whether the reading is successful
• If all the pipes are read, you can consider to exit after the count is 0, or the incoming ctx times out. Is there a better way?
• Each round of comparison only reads one value from buf, and other elements need to be put back, so the position of the current minimum value should be recorded
• Before traversing the Head access element, the length of Tmp must be determined

The code is as follows

``````func Sort(ctx context.Context, out chan<- int, in ... <-chan int) {
//Initialize buf
for i:=0;i!=len(in);i++{
Tmp:make(chan int,1),
})
}
ticker := time.NewTicker(time.Millisecond*10)

for{
select {
case <-ctx.Done():
// Processing exit
ticker.Stop()
return
case <-ticker.C:
count := 0
//It's worth it. Don't read it
count++
continue
}
select {
case v,ok :=<-in[i]:
// Judge whether it is readable
if ok{
count ++
}
default:
}
}
if count == 0{
return
}

// Mark the channel number and value of the minimum value
minId :=-1
var min int

// Skip empty
continue
}

// Initialization minimum
if minId == -1{
minId = i
continue
}
// Compare minimum
if minId !=-1{
//Put back old values
minId = i
} else{
//Put back the new value
}
}
}
//Output min
if minId!=-1{
out<-min
}
}
}
}
``````

The test example is as follows

``````func main() {
ctx, cancel := context.WithCancel(context.Background())
out := make(chan int,100)
in1 := make(chan int,10)
in2 := make(chan int,10)
for i:=0;i!=10;i++{
in1<-i+1

}
for i:=0;i!=10;i++{
in2<-i+3
}

go Sort(ctx, out, in1, in2)
time.Sleep(time.Second*3)

cancel()
close(out)
time.Sleep(time.Second*1)
fmt.Println("end==")
for i := range out{
fmt.Print(i)
}
}
``````

Tags: Programming

Posted on Thu, 26 Mar 2020 10:35:40 -0400 by mikebyrne