【发布时间】:2020-10-23 08:01:56
【问题描述】:
我有两节课。类 Algorithm 实现了一个方法 findIntersections(),它是一个 sweep line algorithm,用于在 O(nLogN) 时间内检查交叉点。
它还实现了一个函数addSegments,它将Segment类型的对象(两个点)添加到基于x坐标的优先队列中。
public class Algorithm {
public PriorityQueue pQueue = new PriortiyQueue();
//This function adds objects of type Segments to a priority queue
public void addSegments(List<Segment> segments) {
pQueue.add(segments);
//do something
}
//This function implements a sweep line algorithm to check for Intersections.
public void findIntersection() {
while (!pQueue.isEmpty()) {
p.poll(); //removes element from Queue
// do something
}
}
}
另一个类Model 将数据从CSV 文件加载到优先队列中。这是一个密集的过程,我只想做一次。
另一方面,checkForCollissions 被调用了数百万次。
-
我想检查提供的段与从 csv 文件添加到优先级队列中的其余段之间的冲突
-
我不想每次都从头开始向优先级队列中添加元素。这是不可行的。
public class Model { public Algorithm algoObj = new Algorithm(); public ArrayList<Segment> algoObj = new ArrayList<>(); public ArrayList<Segment> segments = new ArrayList<>(); public ArrayList<Segment> single_segment = new ArrayList<>(); public boolean loadCSV() { //read csv file while ((strLine = br.readLine()) != null) { segments.add(new Segment()); //Add all segments in CSV file to ArrayLisyt algo.addSegments(segments); //Adds 4000 objects of type segment to priority Queue } } //This function is called millions of times public boolean checkForCollisions(segment_to_check) { single_segment.add(segment_to_check); //Add 1 segment. algoObj.addSegments(single_segment); //Adds 1 object of type segment to priority Queue algoObj.findIntersection(); single_segment.remove(new Segment()); //Remove above segment to get back to original data } }
TL;DR
我遇到的问题是,在第一次调用 checkForCollisions 之后,优先级队列发生了变化,因为 findIntersection() 通过轮询队列中的元素来工作,从而改变队列。
如何防止 algoObj.addSegments() 创建的优先级队列在函数调用之间发生变化?
这是否必须按照here 的解释进行浅层和深层复制?
我尝试在函数开头创建队列的副本,然后更改副本:
public boolean checkForCollisions(segment_to_check) {
Algorithm copy = algoObj;
single_segment.add(segment_to_check); //Add 1 segment.
copy.addSegments(single_segment); //Adds 1 object of type segment to priority Queue
copy.findIntersection();
single_segment.remove(new Segment()); //Remove above segment to get back to original data
}
}
但这不起作用,因为它仍然会改变原始algoObj 的优先级队列。
我相信这是一个初学者的问题,源于我在使用 OO 语言时缺乏正确的理解。任何帮助将不胜感激。
【问题讨论】:
-
您说 findIntersection() 通过轮询队列中的元素来工作,从而改变队列 和 我不想将元素添加到每次都从头开始优先队列。如果
findIntersection修改了队列(这是你的算法),你必须创建一个新的队列对象来传递你拥有的段(注意:你仍然只从文件中读取一次) -
它们是不相关的事件,如果我不清楚,对不起。通过在
loadCSV函数中添加例如 10,000 个线段来设置一次队列。扫描线算法findIntersection通过轮询队列中的元素来工作,从而删除段并更改原始队列。每次检查交叉点时,我都不想再从头开始添加 10,000 条线段。是不是清楚一点? -
这是不可能的,因为您已从队列中删除了项目。你只能避免再次读取文件(我猜你已经做到了)。您可以插入的最大项目数是多少?您为什么担心这个?
-
如果您似乎不想要
Queue的语义,为什么要首先使用PriorityQueue?为什么不直接创建一个List,对其进行一次排序,然后根据需要对其进行迭代? -
那我有点糊涂了。你知道this "limitation" of
PriorityQueue吗?如果在对checkForCollisions的调用之间顺序可以更改,您似乎别无选择,只能删除并重新添加元素。
标签: java queue priority-queue