一种消息接收并打印的结构设计

消息流吐出 2,一种结构接收而不打印 2,因为 1 还没出现。
消息流吐出 1,一种结构接收 1,并且打印:1,2。
消息流吐出 4,一种结构接收而不打印 4,因为 3 还没出现。
消息流吐出 5,一种结构接收而不打印 5,因为 3 还没出现。
消息流吐出 7,一种结构接收而不打印 7,因为 3 还没出现。
消息流吐出 3,一种结构接收 3,并且打印:3,4,5。
消息流吐出 9,一种结构接收而不打印 9,因为 6 还没出现。
消息流吐出 8,一种结构接收而不打印 8,因为 6 还没出现。
消息流吐出 6,一种结构接收 6,并且打印:6,7,8,9。
已知一个消息流会不断地吐出整数1~N,但不一定按照顺序吐出。如果上次打印的数为i,那么当i+1出现时,请打印i+1及其之后接收过的并且连续的所有数,直到1~N全部接收并打印完,请设计这种接收并打印的结构。

应用udp和滑动窗口

思路

把每一个吐出的消息都看成单独的一个集合,每当进入新的集合n时候就进行合并。
与上面n-1合并,与下面的n+1合并
合并的过程就是查找是否有该值,因此使用hashMap分别存放未打印的可能成为头和尾的结点
然后根据即将打印的值,判断本次是否可以打印

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//节点信息
public static class Node{
int value;
Node next;
public Node(int value){
this.value = value;
}
}
public static class MessageBox{
HashMap<Integer, Node> headMap;
HashMap<Integer, Node> tailMap;
//即将打印的数字
int printNum;
public MessageBox(){
//表示未打印集合中的头结点
headMap = new HashMap<Integer, Node>();
//表示未打印集合中的尾结点
tailMap = new HashMap<Integer, Node>();
printNum = 1;
}
public void receive(int value) {
if(value < 1){
return;
}
//把node看做单独的节点
Node node = new Node(value);
headMap.put(value, node);
tailMap.put(value, node);
//由于value-1是头,因此hand中应该包含,而tail中不应该包含
//因此tail去掉value-1,head去掉value
if(tailMap.containsKey(value-1)){
tailMap.get(value-1).next = node;
headMap.remove(value);
tailMap.remove(value-1);
}
//value+1是尾,tail中应该包含,而head中不应该有
//因此head去掉value+1,tail去掉value
if(headMap.containsKey(value+1)){
node.next = headMap.get(value+1);
tailMap.remove(value);
headMap.remove(value+1);
}
//打印,看头结点是否有即将打印的数字
if(headMap.containsKey(printNum)){
printNode();
}
}
public void printNode(){
Node node = headMap.get(printNum);
//因为已经打印,所以head中要去掉
headMap.remove(printNum--);
while (node != null) {
System.out.print(node.value + " ");
node = node.next;
printNum++;
}
System.out.println();
//打印完成后去掉尾结点
tailMap.remove(printNum);
printNum++;
}
}