java双重for实现滑动窗口
时间: 2024-02-25 20:21:25 浏览: 17
可以使用双重for循环来实现滑动窗口。下面是一个使用Java语言实现的示例代码:
```java
public class SlidingWindow {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6};
int k = 3; // 窗口大小
for (int i = 0; i <= nums.length - k; i++) {
for (int j = i; j < i + k; j++) {
System.out.print(nums[j] + " ");
}
System.out.println();
}
}
}
```
在上述代码中,我们使用两个for循环来实现滑动窗口的功能。外层循环控制窗口的起始位置,内层循环用于遍历窗口中的元素。通过控制内层循环的起始位置和结束位置,可以实现滑动窗口移动的效果。
输出结果为:
```
1 2 3
2 3 4
3 4 5
4 5 6
```
这里的示例是基于整数数组的滑动窗口,你也可以根据自己的需求进行适当的修改。希望对你有所帮助!
相关问题
java 实现滑动窗口
以下是 Java 实现滑动窗口的一个示例代码:
```java
public class SlidingWindow {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0 || k <= 0) {
return new int[0];
}
int n = nums.length;
int[] result = new int[n - k + 1];
Deque<Integer> deque = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!deque.isEmpty() && deque.peek() < i - k + 1) {
deque.poll();
}
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
deque.offer(i);
if (i - k + 1 >= 0) {
result[i - k + 1] = nums[deque.peek()];
}
}
return result;
}
}
```
这段代码实现了一个求解滑动窗口最大值的函数,输入是一个整数数组nums和一个整数k,输出是一个数组,表示每个滑动窗口的最大值。
算法的核心思想是维护一个双端队列,队列中存储的是窗口中的下标。遍历整个数组时,我们不断将新的元素加入队列中,同时在队列的两端保持单调性,使得队列中的第一个元素始终是窗口中的最大值。当队列中的最小元素已经不在当前窗口中时,我们将其从队列中移除。当窗口的大小达到k时,我们取出队列中的第一个元素,即为当前窗口的最大值。
用Java实现滑动窗口协议的模拟
以下是用Java实现滑动窗口协议的示例代码:
```java
import java.io.*;
import java.net.*;
import java.util.*;
public class SlidingWindowProtocol {
private static final int WINDOW_SIZE = 4; // 窗口大小
private static final int TIMEOUT = 1000; // 超时时间
public static void main(String[] args) throws Exception {
// 创建服务器套接字
ServerSocket serverSocket = new ServerSocket(8000);
// 等待客户端连接
System.out.println("等待客户端连接...");
Socket clientSocket = serverSocket.accept();
System.out.println("客户端已连接");
// 创建输入输出流
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
// 读取数据包总数
int totalPackets = Integer.parseInt(in.readLine());
System.out.println("数据包总数:" + totalPackets);
// 创建滑动窗口
int base = 0;
int nextSeqNum = 0;
boolean[] acks = new boolean[totalPackets];
List<String> packets = new ArrayList<>();
for (int i = 0; i < totalPackets; i++) {
packets.add(in.readLine());
}
// 发送窗口内的数据包
while (base < totalPackets) {
// 发送窗口内未被确认的数据包
for (int i = base; i < Math.min(base + WINDOW_SIZE, totalPackets); i++) {
if (!acks[i]) {
out.println(i + "," + packets.get(i));
System.out.println("发送数据包:" + i);
}
}
// 等待ACK
Timer timer = new Timer(true);
timer.schedule(new TimerTask() {
@Override
public void run() {
// 超时,重传窗口内未被确认的数据包
for (int i = base; i < Math.min(base + WINDOW_SIZE, totalPackets); i++) {
if (!acks[i]) {
out.println(i + "," + packets.get(i));
System.out.println("重传数据包:" + i);
}
}
}
}, TIMEOUT);
// 接收ACK
while (true) {
String ack = in.readLine();
int ackNum = Integer.parseInt(ack);
System.out.println("接收ACK:" + ackNum);
if (ackNum < base || ackNum >= base + WINDOW_SIZE) {
// ACK不在窗口内,丢弃
continue;
}
acks[ackNum] = true;
if (ackNum == base) {
// 收到窗口内第一个未被确认的ACK,滑动窗口
timer.cancel();
base++;
break;
}
}
}
// 发送结束标记
out.println("-1");
System.out.println("发送结束标记");
// 关闭输入输出流和套接字
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
```
在以上示例代码中,我们模拟了一个简单的滑动窗口协议,用于在客户端和服务器之间传输数据包。服务器使用`ServerSocket`类监听8000端口,并等待客户端连接。一旦客户端连接成功,服务器就可以开始传输数据包。
服务器首先读取数据包总数,然后创建一个滑动窗口,窗口大小为4。服务器将所有数据包保存在一个列表中,然后开始发送窗口内未被确认的数据包。服务器使用`Timer`类创建一个定时器,设置超时时间为1秒。一旦超时,服务器将重传窗口内未被确认的数据包。
服务器同时等待ACK。一旦接收到ACK,服务器就将该ACK标记为已确认,并检查它是否是窗口内第一个未被确认的ACK。如果是,服务器就停止定时器,并滑动窗口。服务器重复以上过程,直到所有数据包都被确认。
在以上示例代码中,我们使用了`java.util.Timer`类实现定时器功能,并使用`java.util.TimerTask`类实现定时任务。在实际应用中,我们可能需要使用更高级别的定时器库,如Netty的`HashedWheelTimer`。