From f5a2fe2d0566016c4a357011c25c50a97813f51f Mon Sep 17 00:00:00 2001 From: luomo233 <157657883@qq.com> Date: Sat, 2 May 2026 17:52:54 +0800 Subject: [PATCH] Refactor node set unify rebuild --- node_path_share.h | 166 +++++++++++++++++++++++------------------- tests/smoke_unify.cpp | 70 ++++++++++++++++++ 2 files changed, 160 insertions(+), 76 deletions(-) create mode 100644 tests/smoke_unify.cpp diff --git a/node_path_share.h b/node_path_share.h index 3e3981e..48824b2 100644 --- a/node_path_share.h +++ b/node_path_share.h @@ -1,7 +1,8 @@ -#pragma once -#include -#include -#include +#pragma once +#include +#include +#include +#include namespace node_path { @@ -776,78 +777,91 @@ namespace node_path return true; } //整合路径节点,最大化共享 - bool unify_node_set() - { - std::vector path_all; - if (get_path_all(path_all) == false)//先获取全部路径的全部节点 - return false; - - //清除原来的数据 - this->node_set.clear(); - this->node_set_free.clear(); - - std::unordered_map>, path_unify_hash> floor_statistic;//按照层级,统计所有相同的信息 - size_t floor_current = 0;//当前层级 - - while (path_all.empty() == false) - { - floor_statistic.clear(); - - size_t pos_path_each = 0; - - //遍历每个层级中的所有节点 - while (pos_path_each < path_all.size()) - { - std::vector::iterator path_each = path_all.begin() + pos_path_each; - - if (floor_current < path_each->nodes.size()) - { - path_unify_construct temp; - - //构建统计信息 - if (floor_current == 0) temp = path_unify_construct(NODE_ROOT_POS, path_each->nodes.front());//如果当前层级是根节点 - else temp = path_unify_construct(static_cast(path_each->nodes[floor_current - 1]), path_each->nodes[floor_current]); - - floor_statistic[temp].emplace_back(std::make_pair(path_each->index, pos_path_each));//统计 - pos_path_each++; - } - else - { - path_all.erase(path_all.begin() + pos_path_each);//当前层级超出了路径长度范围,表明当前路径已经处理完毕,去除当前路径,直到所有路径处理完毕 - } - } - - std::unordered_map>, path_unify_hash>::iterator statistic_each = floor_statistic.begin(); - - //遍历上边的所有统计 - while (statistic_each != floor_statistic.end()) - { - node_pos pos_new = create_ahead(ahead(statistic_each->first.last, statistic_each->first.current, statistic_each->second.size())); - - std::vector>::iterator path_ref = statistic_each->second.begin(); - - //为每个路径构建 - while (path_ref != statistic_each->second.end()) - { - path_info* path_ref_single = get_path_info_by_path_pos_ptr(get_path_pos(path_ref->first)); - - path_ref_single->info.last_pos = pos_new; - - if (floor_current == static_cast((path_ref_single->info.len - 1) / 2)) - path_ref_single->info.mid_pos = pos_new;//更新中点位置 - - path_all[path_ref->second].nodes[floor_current] = static_cast(pos_new);//重复利用空间,保存当前前驱的储存位置 - path_ref++; - } - - statistic_each++; - } - - floor_current++; - } - - return true; - } + bool unify_node_set() + { + std::vector path_all; + if (get_path_all(path_all) == false)//先获取全部路径的全部节点 + return false; + + std::vector node_set_new; + size_t node_ref_total = 0; + for (std::vector::const_iterator path_each = path_all.begin(); path_each != path_all.end(); path_each++) + node_ref_total += path_each->nodes.size(); + node_set_new.reserve(node_ref_total); + + std::unordered_map node_unify_pos; + node_unify_pos.reserve(node_ref_total); + + std::vector> path_info_new; + path_info_new.reserve(path_all.size()); + + for (std::vector::const_iterator path_each = path_all.begin(); path_each != path_all.end(); path_each++) + { + if (path_each->nodes.empty() == true) + return false; + + node_pos pos_last = NODE_ROOT_POS; + node_pos pos_mid = NODE_INVALID_POS; + const size_t pos_mid_target = (path_each->nodes.size() - 1) / 2; + + for (size_t pos_current = 0; pos_current < path_each->nodes.size(); pos_current++) + { + path_unify_construct node_key(pos_last, path_each->nodes[pos_current]); + std::unordered_map::iterator node_find = node_unify_pos.find(node_key); + node_pos pos_new = NODE_INVALID_POS; + + if (node_find == node_unify_pos.end()) + { + pos_new = static_cast(node_set_new.size()); + node_set_new.emplace_back(pos_last, path_each->nodes[pos_current], 0); + node_unify_pos.emplace(node_key, pos_new); + } + else + { + pos_new = node_find->second; + } + + node_set_new[pos_new].ref++; + + if (pos_current == pos_mid_target) + pos_mid = pos_new; + + pos_last = pos_new; + } + + if (pos_mid == NODE_INVALID_POS || pos_last == NODE_INVALID_POS) + return false; + + path_info_new.emplace_back(path_each->index, path_info_base(pos_last, pos_mid, static_cast(path_each->nodes.size()))); + } + + for (std::vector::const_iterator node_each = node_set_new.begin(); node_each != node_set_new.end(); node_each++) + { + if (node_each->test_validity_index() == false || node_each->test_validity_ref() == false) + return false; + if (node_each->last != NODE_ROOT_POS && node_each->last >= node_set_new.size()) + return false; + } + + for (std::vector>::const_iterator path_each = path_info_new.begin(); path_each != path_info_new.end(); path_each++) + { + if (test_validity_path_pos(get_path_pos(path_each->first)) == false) + return false; + } + + this->node_set = std::move(node_set_new); + this->node_set_free.clear(); + + for (std::vector>::const_iterator path_each = path_info_new.begin(); path_each != path_info_new.end(); path_each++) + { + path_info* path_info_target = get_path_info_by_path_pos_ptr(get_path_pos(path_each->first)); + path_info_target->info.last_pos = path_each->second.last_pos; + path_info_target->info.mid_pos = path_each->second.mid_pos; + path_info_target->info.len = path_each->second.len; + } + + return true; + } //获取系统状态 path_state_statistic get_state() const noexcept { diff --git a/tests/smoke_unify.cpp b/tests/smoke_unify.cpp new file mode 100644 index 0000000..2d85456 --- /dev/null +++ b/tests/smoke_unify.cpp @@ -0,0 +1,70 @@ +#include "../node_path_share.h" + +#include +#include + +using namespace node_path; + +static std::vector read_path(path_share& paths, path_index index) +{ + path result; + assert(paths.get_path(index, result)); + return result.nodes; +} + +int main() +{ + path_share paths; + + path_index main_path = paths.create_path(1); + assert(main_path != PATH_INVALID_INDEX); + assert(paths.add_path_node(main_path, std::vector({ 2, 3, 4, 5 }))); + + path_index branch_one = paths.create_branch(main_path, 2, 6); + assert(branch_one != PATH_INVALID_INDEX); + path_index branch_two = paths.create_branch(main_path, 3, 7); + assert(branch_two != PATH_INVALID_INDEX); + + path_index same_one = paths.create_path(10); + assert(same_one != PATH_INVALID_INDEX); + assert(paths.add_path_node(same_one, std::vector({ 11, 12 }))); + + path_index same_two = paths.create_path(10); + assert(same_two != PATH_INVALID_INDEX); + assert(paths.add_path_node(same_two, std::vector({ 11, 12 }))); + + path_index sparse_path = paths.create_path(20); + assert(sparse_path != PATH_INVALID_INDEX); + assert(paths.add_path_node(sparse_path, std::vector({ 21, 22 }))); + assert(paths.del_path_node_single(sparse_path, 1)); + + const std::vector main_before = read_path(paths, main_path); + const std::vector branch_one_before = read_path(paths, branch_one); + const std::vector branch_two_before = read_path(paths, branch_two); + const std::vector same_one_before = read_path(paths, same_one); + const std::vector same_two_before = read_path(paths, same_two); + const std::vector sparse_before = read_path(paths, sparse_path); + + const path_state_statistic before = paths.get_stastic(); + assert(before.quantity_bytes_memory_alloc > before.quantity_bytes_memory_used); + + assert(paths.unify()); + + const path_state_statistic after = paths.get_stastic(); + assert(after.quantity_bytes_memory_alloc == after.quantity_bytes_memory_used); + assert(after.quantity_bytes_memory_alloc < before.quantity_bytes_memory_alloc); + + assert(read_path(paths, main_path) == main_before); + assert(read_path(paths, branch_one) == branch_one_before); + assert(read_path(paths, branch_two) == branch_two_before); + assert(read_path(paths, same_one) == same_one_before); + assert(read_path(paths, same_two) == same_two_before); + assert(read_path(paths, sparse_path) == sparse_before); + + assert(paths.get_path_node_index(main_path, 2) == main_before[2]); + assert(paths.get_path_node_index(branch_one, 1) == branch_one_before[1]); + assert(paths.get_path_node_index(branch_two, 3) == branch_two_before[3]); + assert(paths.get_path_node_index(sparse_path, 1) == sparse_before[1]); + + return 0; +}