因为项目原因,需要对现有的200G的数据上进行时间秒级的测试,其中一个就是两个节点之间的路径搜索,按照之前测试思路,很自然想到树的深度搜索算法,用Java递归实现,部分代码如下:
public static void main(String[] args) throws SQLException {
ArrayList<ArrayList<String>> list = new ArrayList<>();//储存不同的路径节点信息
ArrayList<String> item = new ArrayList<>();//储存的是每个路径的信息,多个路径信息都存在list中
try {
MongoClient client = new MongoClient("192.168.1.111", 27016);
MongoDatabase db = client.getDatabase("wq");
col = db.getCollection("ljgx");
// System.out.println("wnjd connect .");
col1 = db.getCollection("ljgx");
System.out.println("ljgx connect .");
start = System.currentTimeMillis();
start = System.currentTimeMillis();
System.out.println(start);
finding1(jd1, list, item);
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
public static ArrayList<ArrayList<String>> finding1(String jd, ArrayList<ArrayList<String>> list, ArrayList<String> item) {
item.add(jd);
BasicDBObject query1 = new BasicDBObject();
query1.put("网内节点1编号", jd);
FindIterable<Document> findIterable = col.find(query1);
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
// start1 = System.currentTimeMillis();
Document d = mongoCursor.next();
String a = d.get("网内节点2编号").toString();
if (a.equals(jd2)) {
item.add(d.get("网内节点2编号").toString());
list.add(item);
item.clear();
}
item.add(d.get("网内节点2编号").toString());
finding1(d.get("网内节点2编号").toString(),list,item);
}
return list;
}
以上代码可以在数据量小的情况下正常执行,并且找到两个节点间的路径,但是200G的数据量下就会报一下错误,实际项目要求是6T
溢出错误,所以只有将递归实现改为了非递归实现
在这又遇到一个问题,对于树的深度搜索遍历的非递归实现不是很清楚,一开始写的代码如下:
public static void deepOrder(String jd) {
ArrayDeque<Node> s = new ArrayDeque<>();
ArrayList<Node> list = new ArrayList<>();
int level = 0;
Node n = new Node(jd, level);
s.push(n);
while (!s.isEmpty()) {
String now = s.pop();// 出栈,此时第一次出栈后栈为空
list.add(now);
if (jd.equals(jd2)) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i).jd + " ");
}
System.out.println();
}
else {
BasicDBObject query1 = new BasicDBObject();
query1.put("网内节点1编号", jd);
FindIterable<Document> findIterable = col.find(query1);
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
Document d = mongoCursor.next();
String a = d.get("网内节点2编号").toString();
s.push(a);
}
}
}
}
以上代码代码并不能得到想要的数据,归根于遍历后的数据不知道哪些该删除,该保留,怎么删除,对于数据组织上还有欠缺
代码的改进方法:
1、利用层级的思想来判断如何删掉数据
2、每个节点为一个Node对象,每个node对象下拥有一个childeList来保存自己的孩子节点
实现1:
代码如下:
public static void main(String[] args) throws SQLException {
try {
MongoClient client = new MongoClient("192.168.1.111", 27016);
MongoDatabase db = client.getDatabase("wq");
col = db.getCollection("ljgx");
System.out.println("ljgx connect .");
start = System.currentTimeMillis();
System.out.println(start);
deepOrder(jd1);
// System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void deepOrder(String jd) {
ArrayDeque<Node> s = new ArrayDeque<>();
ArrayList<Node> list = new ArrayList<>();
int level = 0;
Node n = new Node(jd, level);
s.push(n);
while (!s.isEmpty()) {
Node now = s.pop();// 出栈,此时第一次出栈后栈为空
while (list.size() > 0 && list.get(list.size() - 1).level >= now.level) {
list.remove(list.size() - 1);
}
list.add(now);
if (now.jd.equals(jd2)) {
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i).jd + " ");
}
System.out.println();
}
else {
BasicDBObject query1 = new BasicDBObject();
level = now.level + 1;
query1.put("网内节点1编号", now.jd);
FindIterable<Document> findIterable = col.find(query1);
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
Document d = mongoCursor.next();
String a = d.get("网内节点2编号").toString();
n = new Node(a, level);
s.push(n);
}
}
}
}
}
class Node {
String jd;
int level;
public Node(String no, int level) {
this.jd = no;
this.level = level;
}
}
这个代码可以实现多叉树的深度遍历搜索算法(非递归),可以在小数据量上得到结果,大数据量上没有报错,但是时间很长,依然在运行
2、第二种方法没有实现,但是耗费的空间比第一种还多,所以就放弃实现了