package com.qixian.general.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qixian.general.dao.HardRecordDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@RestController
@RequestMapping("/apiqixian/BPlusTree")
public class BPlusTree {
@Autowired
private HardRecordDao hardRecordDao;
//ID主键索引树
static List<JSONObject> root = new ArrayList<JSONObject>();
//联合索引字段B+树
static List<JSONObject> joinTree = new ArrayList<JSONObject>();
//从下往上构建联合索引树
@GetMapping("/createBPlusTreeByIndexVocabularyAndGradationAndLastCreatedTimeAndDisabled")
public List<JSONObject> createBPlusTreeByIndexVocabularyAndGradationAndLastCreatedTimeAndDisabled(HttpServletRequest request) throws InterruptedException {
List<JSONObject> jsonObjects = hardRecordDao.listBy(new HashMap<String, Object>());
List<JSONObject> jsonObjects1 = new ArrayList<JSONObject>();
//选取联合查询字段和ID进集合
for (int i = 0; i < jsonObjects.size(); i++) {
JSONObject item = new JSONObject();
item.put("indexVocabulary", jsonObjects.get(i).getString("indexVocabulary"));
item.put("gradation", jsonObjects.get(i).getInteger("gradation"));
item.put("lastCreatedTime", jsonObjects.get(i).getLong("lastCreatedTime"));
item.put("disabled", jsonObjects.get(i).getInteger("disabled"));
item.put("id", jsonObjects.get(i).getInteger("id"));
jsonObjects1.add(item);
}
//冒泡排序,按照indexVocabulary从小到大排序
for (int i = 0; i < jsonObjects1.size(); i++) {
for (int j = 0; j < jsonObjects1.size() - i - 1; j++) {
//从上往下相邻比对,重的往下沉
if (Integer.parseInt(jsonObjects1.get(j).getString("indexVocabulary")) > Integer.parseInt(jsonObjects1.get(j + 1).getString("indexVocabulary"))) {
JSONObject jsonObject = jsonObjects1.get(j + 1);
jsonObjects1.set(j + 1, jsonObjects1.get(j));
jsonObjects1.set(j, jsonObject);
}
}
}
//冒泡排序,indexVocabulary相等的情况下根据gradation从小到大排序
for (int i = 0; i < jsonObjects1.size(); i++) {
for (int j = 0; j < jsonObjects1.size() - i - 1; j++) {
if (jsonObjects1.get(j).getString("indexVocabulary").equals(jsonObjects1.get(j + 1).getString("indexVocabulary")) && jsonObjects1.get(j).getInteger("gradation") > jsonObjects1.get(j + 1).getInteger("gradation")) {
JSONObject jsonObject = jsonObjects1.get(j + 1);
jsonObjects1.set(j + 1, jsonObjects1.get(j));
jsonObjects1.set(j, jsonObject);
}
}
}
//冒泡排序,gradation相等的情况下根据lastCreatedTime从小到大排序
for (int i = 0; i < jsonObjects1.size(); i++) {
for (int j = 0; j < jsonObjects1.size() - i - 1; j++) {
if (jsonObjects1.get(j).getInteger("gradation") == jsonObjects1.get(j + 1).getInteger("gradation") && jsonObjects1.get(j).getLong("lastCreatedTime") > jsonObjects1.get(j + 1).getLong("lastCreatedTime")) {
JSONObject jsonObject = jsonObjects1.get(j + 1);
jsonObjects1.set(j + 1, jsonObjects1.get(j));
jsonObjects1.set(j, jsonObject);
}
}
}
//冒泡排序,lastCreatedTime相等的情况下根据disabled从小到大排序
for (int i = 0; i < jsonObjects1.size(); i++) {
for (int j = 0; j < jsonObjects1.size() - i - 1; j++) {
if (jsonObjects1.get(j).getInteger("disabled") > jsonObjects1.get(j + 1).getInteger("disabled") && jsonObjects1.get(j).getLong("lastCreatedTime") == jsonObjects1.get(j + 1).getLong("lastCreatedTime")) {
JSONObject jsonObject = jsonObjects1.get(j + 1);
jsonObjects1.set(j + 1, jsonObjects1.get(j));
jsonObjects1.set(j, jsonObject);
}
}
}
//给排好序的集合两两相邻元素互相配置pre字段指向前一个元素,next字段指向后一个元素
for (int i = 0; i < jsonObjects1.size() - 1; i++) {
jsonObjects1.get(i).put("next", jsonObjects1.get(i + 1));
jsonObjects1.get(i + 1).put("pre", jsonObjects1.get(i));
}
//集合按照10个一组,计算总共有多少组
int i1 = (int) Math.ceil((double) jsonObjects1.size() / 10);
//第三层总集合
List<JSONObject> threeListAll = new ArrayList<JSONObject>();
//对集合进行每十个一组,所有的组装进threeListAll集合
for (int i = 0; i < i1; i++) {
JSONObject threeFloor = new JSONObject();
List<JSONObject> leafList = new ArrayList<JSONObject>();
for (int j = 0; j < 10; j++) {
if (i * 10 + j < jsonObjects1.size()) {
//将每组第一个元素的联合索引字段保存进叶子元素作为该组各个字段的最小值代表
if (j == 0) {
threeFloor.put("indexVocabulary", jsonObjects1.get(i * 10 + j).getString("indexVocabulary"));
threeFloor.put("gradation", jsonObjects1.get(i * 10 + j).getInteger("gradation"));
threeFloor.put("lastCreatedTime", jsonObjects1.get(i * 10 + j).getLong("lastCreatedTime"));
threeFloor.put("disabled", jsonObjects1.get(i * 10 + j).getInteger("disabled"));
}
leafList.add(jsonObjects1.get(i * 10 + j));
}
}
threeFloor.put("leafList", leafList);
threeListAll.add(threeFloor);
}
//计算第三层按照每10个一组总共能分成多少组
int i2 = (int) Math.ceil((double) threeListAll.size() / 10);
//第二层所有分组的总集合
List<JSONObject> secondListAll = new ArrayList<JSONObject>();
//对集合进行每十个一组,所有的组装进secondListAll集合
for (int i = 0; i < i2; i++) {
JSONObject secondFloor = new JSONObject();
List<JSONObject> threeList = new ArrayList<JSONObject>();
for (int j = 0; j < 10; j++) {
if (i * 10 + j < threeListAll.size()) {
//将每组第一个元素的联合索引字段保存进叶子元素作为该组各个字段的最小值代表
if (j == 0) {
secondFloor.put("indexVocabulary", threeListAll.get(i * 10 + j).getString("indexVocabulary"));
secondFloor.put("gradation", threeListAll.get(i * 10 + j).getInteger("gradation"));
secondFloor.put("lastCreatedTime", threeListAll.get(i * 10 + j).getLong("lastCreatedTime"));
secondFloor.put("disabled", threeListAll.get(i * 10 + j).getInteger("disabled"));
}
threeList.add(threeListAll.get(i * 10 + j));
}
}
secondFloor.put("threeList", threeList);
secondListAll.add(secondFloor);
}
//计算第二层按照每10个一组总共能分成多少组
int i3 = (int) Math.ceil((double) secondListAll.size() / 10);
//第一层所有分组的总集合
List<JSONObject> firstListAll = new ArrayList<JSONObject>();
//对集合进行每十个一组,所有的组装进firstListAll集合
for (int i = 0; i < i3; i++) {
JSONObject firstFloor = new JSONObject();
List<JSONObject> secondList = new ArrayList<JSONObject>();
for (int j = 0; j < 10; j++) {
if (i * 10 + j < secondListAll.size()) {
//将每组第一个元素的联合索引字段保存进叶子元素作为该组各个字段的最小值代表
if (j == 0) {
firstFloor.put("indexVocabulary", secondListAll.get(i * 10 + j).getString("indexVocabulary"));
firstFloor.put("gradation", secondListAll.get(i * 10 + j).getInteger("gradation"));
firstFloor.put("lastCreatedTime", secondListAll.get(i * 10 + j).getLong("lastCreatedTime"));
firstFloor.put("disabled", secondListAll.get(i * 10 + j).getInteger("disabled"));
}
secondList.add(secondListAll.get(i * 10 + j));
}
}
firstFloor.put("secondList", secondList);
firstListAll.add(firstFloor);
}
//第一层所有分组的集合
joinTree = firstListAll;
return null;
}
//根据联合索引字段范围检索联合索引树
@GetMapping("/getBPlusTreeWhere")
public List<JSONObject> getBPlusTreeWhere(HttpServletRequest request, Integer minIndexVocabulary, Integer maxIndexVocabulary,
Integer minGradation, Integer maxGradation, Long minLastCreatedTime, Long maxLastCreatedTime, Integer disabled) throws InterruptedException {
int sumCount = 0;
JSONArray target = null;
//遍历联合索引树
for (int i = 0; i < joinTree.size(); i++) {
sumCount++;
//如果第一层的当前分组的indexVocabulary最小值大于索引条件范围的最大值,那么说明符合条件的数据在上一个分组
if (joinTree.get(i).getInteger("indexVocabulary") > maxIndexVocabulary) {
//把上限的数据肯定在上一个分组,所以这里获取i-1
target = joinTree.get(i - 1).getJSONArray("secondList");
break;
}
//如果i == joinTree.size() - 1,说明遍历到第一层最后一个分组,依然没找到分组的最小值大于maxIndexVocabulary,那么说明maxIndexVocabulary存在在当前分组中(假设我们测试模拟的范围条件没有超出集合范围)
if (i == joinTree.size() - 1) {
target = joinTree.get(i).getJSONArray("secondList");
break;
}
}
//遍历第二层的分组
for (int j = 0; j < target.size(); j++) {
sumCount++;
//如果第二层的当前分组的indexVocabulary最小值大于索引条件范围的最大值,那么说明符合条件的数据在上一个分组
if (target.getJSONObject(j).getInteger("indexVocabulary") > maxIndexVocabulary) {
target = target.getJSONObject(j - 1).getJSONArray("threeList");
break;
}
//如果i == target.size() - 1,说明遍历到第一层最后一个分组,依然没找到分组的最小值大于maxIndexVocabulary,那么说明maxIndexVocabulary存在在当前分组中(假设我们测试模拟的范围条件没有超出集合范围)
if (j == target.size() - 1) {
target = target.getJSONObject(j).getJSONArray("threeList");
break;
}
}
//遍历第三层的分组
for (int j = 0; j < target.size(); j++) {
sumCount++;
if (target.getJSONObject(j).getInteger("indexVocabulary") > maxIndexVocabulary) {
target = target.getJSONObject(j - 1).getJSONArray("leafList");
break;
}
if (j == target.size() - 1) {
target = target.getJSONObject(j).getJSONArray("leafList");
break;
}
}
//遍历叶子结点的集合
for (int i = 0; i < target.size(); i++) {
//如果元素的indexVocabulary>maxIndexVocabulary,则说明符合要求的元素都在pre前面的元素中
if (target.getJSONObject(i).getInteger("indexVocabulary") > maxIndexVocabulary) {
//end是起点,根据起点往前遍历
JSONObject end = target.getJSONObject(i);
//死循环,从end起点元素往前找,找到第一个符合联合查询条件的元素
while (true) {
//判断条件顺序从indexVocabulary—>gradation->lastCreatedTime->disabled,顺序,不符合indexVocabulary条件的就不要比对gradation,不符合gradation的就不要比对lastCreatedTime,以此类推
if (end.getInteger("indexVocabulary") <= maxIndexVocabulary && end.getInteger("gradation") <= maxGradation
&& end.getLong("lastCreatedTime") <= maxLastCreatedTime
&& end.getInteger("disabled") == disabled) {
res = new ArrayList<JSONObject>();
//找到符合条件的起始元素,从该元素开始往前遍历,符合条件的加入结果集合中
getResArr(end, minIndexVocabulary, minGradation, maxGradation, minLastCreatedTime, maxLastCreatedTime, disabled);
// for(int j=0;j<res.size();j++){
// res.get(j).put("pre",null);
// res.get(j).put("next",null);
// }
return res;
} else {
end = end.getJSONObject("pre");
}
}
}
//i == target.size() - 1,说明本循环到循环最后一遍了,依然没找到indexVocabulary>maxIndexVocabulary的起点元素,说明该组最后一个元素就是小于maxIndexVocabulary的起点元素,当前元素就是起点
if (i == target.size() - 1) {
JSONObject end = target.getJSONObject(i);
//死循环,从end起点元素往前找,找到第一个符合联合查询条件的元素
while (true) {
//判断条件顺序从indexVocabulary—>gradation->lastCreatedTime->disabled,顺序,不符合indexVocabulary条件的就不要比对gradation,不符合gradation的就不要比对lastCreatedTime,以此类推
if (end.getInteger("indexVocabulary") <= maxIndexVocabulary && end.getInteger("gradation") <= maxGradation
&& end.getLong("lastCreatedTime") <= maxLastCreatedTime
&& end.getInteger("disabled") == disabled) {
res = new ArrayList<JSONObject>();
//找到符合条件的起始元素,从该元素开始往前遍历,符合条件的加入结果集合中
getResArr(end, minIndexVocabulary, minGradation, maxGradation, minLastCreatedTime, maxLastCreatedTime, disabled);
// for(int j=0;j<res.size();j++){
// res.get(j).put("pre",null);
// res.get(j).put("next",null);
// }
return res;
} else {
end = end.getJSONObject("pre");
}
}
}
}
return null;
}
List<JSONObject> res = new ArrayList<JSONObject>();
//往前遍历将符合条件的加入结果集中,直到indexVocabulary<minIndexVocabulary时结束
void getResArr(JSONObject end, Integer minIndexVocabulary, Integer minGradation, Integer maxGradation, Long minLastCreatedTime, Long maxLastCreatedTime, Integer disabled) throws InterruptedException {
//当前元素的indexVocabulary>= minIndexVocabulary时,进一步判断,如果符合条件则加入结果集中,并往前遍历,否则结束循环
if (end.getInteger("indexVocabulary") >= minIndexVocabulary) {
if (end.getInteger("gradation") >= minGradation && end.getInteger("gradation") <= maxGradation) {
if (end.getLong("lastCreatedTime") >= minLastCreatedTime && end.getLong("lastCreatedTime") <= maxLastCreatedTime
) {
if (end.getInteger("disabled") == disabled) {
//这里用克隆,防止断开前后连接时影响到构建的索引树
JSONObject clone = (JSONObject) end.clone();
clone.put("pre", null);
clone.put("next", null);
//检索到符合联合检索条件的元素,根据元素的ID向主键索引树检索到对应元素的所有信息,加入到结果集中
JSONObject id = (JSONObject) getBPlusTree(null, clone.getInteger("id")).clone();
//将该元素向前指引的字段断开,不然每个元素都包含了所有前面的元素,没有意义,只会加大集合大小
id.put("preObject", null);
res.add(id);
}
}
}
//如果当前元素的前面有元素,则往前循环,没有元素说明到头了,结束循环
if (end.getJSONObject("pre") != null) {
getResArr(end.getJSONObject("pre"), minIndexVocabulary, minGradation, maxGradation, minLastCreatedTime, maxLastCreatedTime, disabled);
}
}
}
//从上往下构建主键索引树
@GetMapping("/createBPlusTree")
public JSONObject createBPlusTree(HttpServletRequest request) throws InterruptedException {
List<JSONObject> jsonObjects = hardRecordDao.listBy(new HashMap<String, Object>());
//将数据分11组,每组1000数据
for (int i = 0; i < 11; i++) {
JSONObject firstFloor = new JSONObject();
//每组ID的最小值是i * 1000+1
firstFloor.put("minIndex", i * 1000 + 1);
List<JSONObject> secondList = new ArrayList<JSONObject>();
//将本组的数据再分10组,每组100数据
for (int j = 0; j < 10; j++) {
JSONObject secondFloor = new JSONObject();
//每组ID的最小值是i * 1000 + j * 100+1
secondFloor.put("minIndex", i * 1000 + j * 100 + 1);
List<JSONObject> threeList = new ArrayList<JSONObject>();
//将本组的数据再分10组,每组10数据
for (int m = 0; m < 10; m++) {
JSONObject threeFloor = new JSONObject();
//每组ID的最小值是i * 1000 + j * 100 + m * 10+1
threeFloor.put("minIndex", i * 1000 + j * 100 + m * 10 + 1);
List<JSONObject> leafList = new ArrayList<JSONObject>();
//循环原集合,将符合当前第一层当前组,第二层当前组,第三层当前组的数据加入当前层的当前组
for (int n = 0; n < jsonObjects.size(); n++) {
//判断id是否大于当前第三组的最小值,小于当前组的最大值
if (jsonObjects.get(n).getInteger("id") > (i * 1000 + j * 100 + m * 10) && jsonObjects.get(n).getInteger("id") <= (i * 1000 + j * 100 + m * 10 + 10)) {
//判断是否是第一层的第一组,第二层的第一组,第三层的第一组,并且叶子集合是0,如果是,说明该元素是索引树的第一个元素,不需要设置连接指向前一个元素
if (i == 0 && j == 0 && m == 0 && leafList.size() == 0) {
leafList.add(jsonObjects.get(n));
} else if (i > 0 && j == 0 && m == 0 && leafList.size() == 0) {//判断不是第一层的第一组,但是是第二层的第一组,第三层的第一组,叶子组的第一个元素,则设置连接指向前一个第一层分组的最后一个元素
jsonObjects.get(n).put("preObject", root.get(i - 1).getJSONArray("secondList").getJSONObject(9).getJSONArray("threeList").getJSONObject(9).getJSONArray("leafList").getJSONObject(9));
leafList.add(jsonObjects.get(n));
} else if (j > 0 && m == 0 && leafList.size() == 0) {//判断不是第一层的第一组,也不是第二层的第一个分组,但是是第三层的第一组,叶子组的第一个元素,则设置连接指向前一个第二层分组的最后一个元素
jsonObjects.get(n).put("preObject", secondList.get(j - 1).getJSONArray("threeList").getJSONObject(9).getJSONArray("leafList").getJSONObject(9));
leafList.add(jsonObjects.get(n));
} else if (m > 0 && leafList.size() == 0) {//判断不是第一层的第一组,也不是第二层的第一个分组,也不是第三层的第一个分组,但是叶子组的第一个元素,则设置连接指向前一个叶子组的最后一个元素
try {
jsonObjects.get(n).put("preObject", threeList.get(m - 1).getJSONArray("leafList").getJSONObject(threeList.get(m - 1).getJSONArray("leafList").size() - 1));
} catch (Exception e) {
System.out.println();
System.out.println(jsonObjects.get(n).getInteger("id"));
System.out.println(threeList.get(m - 1).getJSONArray("leafList").size());
}
leafList.add(jsonObjects.get(n));
} else {//把以上各层第一个组的第一个元素的特殊情况都排除完了,这里的元素就都是本组内后边的元素,只需要将他们的前置连接设置为前一个元素即可
jsonObjects.get(n).put("preObject", leafList.get(leafList.size() - 1));
//组件叶子组集合
leafList.add(jsonObjects.get(n));
}
}
}
//将叶子组集合赋给第三层对象
threeFloor.put("leafList", leafList);
//组件第三层组集合
threeList.add(threeFloor);
}
//将第三层组集合赋给第二层
secondFloor.put("threeList", threeList);
secondList.add(secondFloor);
}
//将第二层组集合赋给第一层
firstFloor.put("secondList", secondList);
//构建第一层集合
root.add(firstFloor);
}
return null;
}
//根据主键范围检索主键索引树
@GetMapping("/getBPlusTreeByRang")
public JSONArray getBPlusTreeByRang(HttpServletRequest request, Integer minId, Integer maxId) throws InterruptedException {
int sumCount = 0;
for (int i = 0; i < root.size(); i++) {
sumCount++;
if (root.get(i).getInteger("minIndex") > maxId) {
for (int j = 0; j < root.get(i - 1).getJSONArray("secondList").size(); j++) {
sumCount++;
if (root.get(i - 1).getJSONArray("secondList").getJSONObject(j).getInteger("minIndex") > maxId) {
for (int m = 0; m < root.get(i - 1).getJSONArray("secondList").getJSONObject(j - 1).getJSONArray("threeList").size(); m++) {
sumCount++;
if (root.get(i - 1).getJSONArray("secondList").getJSONObject(j - 1).getJSONArray("threeList").getJSONObject(m).getInteger("minIndex") > maxId) {
JSONArray jsonArray = root.get(i - 1).getJSONArray("secondList").getJSONObject(j - 1).getJSONArray("threeList").getJSONObject(m - 1).getJSONArray("leafList");
for (int n = 0; n < jsonArray.size(); n++) {
sumCount++;
if (jsonArray.getJSONObject(n).getInteger("id").intValue() == maxId) {
System.out.println("循环了" + sumCount + "次");
JSONArray resArr = new JSONArray();
JSONObject clone = (JSONObject) jsonArray.getJSONObject(n).clone();
clone.put("preObject", null);
resArr.add(clone);
JSONObject preObj = jsonArray.getJSONObject(n).getJSONObject("preObject");
while (preObj.getInteger("id") >= minId) {
JSONObject clone1 = (JSONObject) preObj.clone();
clone1.put("preObject", null);
resArr.add(clone1);
preObj = preObj.getJSONObject("preObject");
}
return resArr;
}
}
}
}
}
}
}
}
return null;
}
@GetMapping("/getBPlusTree")
public JSONObject getBPlusTree(HttpServletRequest request, Integer id) throws InterruptedException {
int sumCount = 0;
JSONArray target = null;
//循环第一层组集合
for (int i = 0; i < root.size(); i++) {
sumCount++;
//如果本组的最小值大于条件id,则目标数据在前一个第一层分组
if (root.get(i).getInteger("minIndex") > id) {
target = root.get(i - 1).getJSONArray("secondList");
break;
}
//如果本组的最小值等于条件id,则目标数据在当前的第一层分组
if (root.get(i).getInteger("minIndex") == id) {
target = root.get(i).getJSONArray("secondList");
break;
}
//如果循环最后一遍,没找到第一层分组的最小值minIndex>=id,说明目标数据在最后一个第一层分组(假设我们要找的数据存在)
if (i == root.size() - 1) {
target = root.get(i).getJSONArray("secondList");
break;
}
}
//循环第二层组集合
for (int j = 0; j < target.size(); j++) {
sumCount++;
//如果本组的最小值大于条件id,则目标数据在前一个第二层分组
if (target.getJSONObject(j).getInteger("minIndex") > id) {
target = target.getJSONObject(j - 1).getJSONArray("threeList");
break;
}
//如果本组的最小值等于条件id,则目标数据在当前的第二层分组
if (target.getJSONObject(j).getInteger("minIndex") == id) {
target = target.getJSONObject(j).getJSONArray("threeList");
break;
}
//如果循环最后一遍,没找到第二层分组的最小值minIndex>=id,说明目标数据在最后一个第二层分组(假设我们要找的数据存在)
if (j == target.size() - 1) {
target = target.getJSONObject(j).getJSONArray("threeList");
break;
}
}
//循环第三层组集合
for (int j = 0; j < target.size(); j++) {
sumCount++;
if (target.getJSONObject(j).getInteger("minIndex") > id) {
target = target.getJSONObject(j - 1).getJSONArray("leafList");
break;
}
if (target.getJSONObject(j).getInteger("minIndex") == id) {
target = target.getJSONObject(j).getJSONArray("leafList");
break;
}
if (j == target.size() - 1) {
target = target.getJSONObject(j).getJSONArray("leafList");
break;
}
}
//循环叶子组集合
for (int n = 0; n < target.size(); n++) {
sumCount++;
//如果id相等,则获得所要查询的元素
if (target.getJSONObject(n).getInteger("id").intValue() == id) {
try {
System.out.println("循环了" + sumCount + "次");
} catch (Exception e) {
int i = 9;
}
return target.getJSONObject(n);
}
}
return null;
}
}
粗略模拟B+树的构建和查询
最新推荐文章于 2024-06-10 13:00:48 发布