192 lines
5.2 KiB
C++
192 lines
5.2 KiB
C++
#include "Tree_Model.h"
|
|
#include <queue>
|
|
#include <stack>
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
namespace Flex_Qt {
|
|
int Tree_Node::get_deep() {
|
|
int ret = -1;
|
|
Tree_Node* cur = static_cast<Tree_Node*>(this);
|
|
while (cur) {
|
|
cur = cur->par;
|
|
ret++;
|
|
}
|
|
return ret;
|
|
}
|
|
Tree_Node::Tree_Node() {}
|
|
int Tree_Node::index() {
|
|
auto found = std::find(par->sons.begin(), par->sons.end(), static_cast<Tree_Node*>(this));
|
|
return found == par->sons.end() ? -1 : static_cast<int>(std::distance(par->sons.begin(), found));
|
|
}
|
|
bool Tree_Node::is_root() {
|
|
return par == nullptr;
|
|
}
|
|
bool Tree_Node::is_leaf() {
|
|
return !sons.size();
|
|
}
|
|
bool Tree_Node::is_first() {
|
|
return index() == 0;
|
|
}
|
|
bool Tree_Node::is_last() {
|
|
return index() == par->sons.size() - 1;
|
|
}
|
|
Tree_Node* Tree_Node::previous() {
|
|
if (is_first())
|
|
return nullptr;
|
|
return par->sons[index() - 1];
|
|
}
|
|
Tree_Node* Tree_Node::next() {
|
|
if (is_last())
|
|
return nullptr;
|
|
return par->sons[index() + 1];
|
|
}
|
|
Tree_Node* Tree_Node::last_child() {
|
|
if (is_leaf())
|
|
std::cout << "last_child() error";
|
|
return sons[sons.size() - 1];
|
|
}
|
|
Tree_Node* Tree_Node::first_child() {
|
|
if (is_leaf())
|
|
std::cout << "first_child() error";
|
|
return sons[0];
|
|
}
|
|
Tree_Node* Tree_Node::root() {
|
|
Tree_Node * ret = static_cast<Tree_Node*>(this);
|
|
while (ret->par != nullptr) {
|
|
ret = ret->par;
|
|
}
|
|
return ret;
|
|
}
|
|
std::vector<Tree_Node*> Tree_Node::deep_traversed() {
|
|
std::vector<Tree_Node*> result;
|
|
if (!this)
|
|
return result;
|
|
std::stack<Tree_Node*> stack;
|
|
stack.push(this);
|
|
while (!stack.empty()) {
|
|
Tree_Node * node = stack.top();
|
|
stack.pop();
|
|
result.push_back(node);
|
|
// 逆序压入子节点,保证从左到右的遍历顺序
|
|
for (int i = node->sons.size() - 1; i >= 0; --i) {
|
|
stack.push(node->sons[i]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
std::vector<Tree_Node*> Tree_Node::sequence_traversed() {
|
|
std::vector<Tree_Node*> ret;
|
|
std::queue<Tree_Node*> que;
|
|
Tree_Node * that = this;
|
|
que.push(that);
|
|
while (!que.empty()) {
|
|
Tree_Node * cur = que.front();
|
|
que.pop();
|
|
int n = cur->sons.size();
|
|
ret.push_back(cur);
|
|
for (int i = 0; i < n; ++i) {
|
|
que.push(cur->sons[i]);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
std::vector<Tree_Node*> Tree_Node::descendants() {
|
|
std::vector<Tree_Node*>&& ret = sequence_traversed();
|
|
ret.erase(ret.begin());
|
|
return ret;
|
|
}
|
|
std::vector<Tree_Node*> deep_traversed(const std::vector<Tree_Node*>& nodes) {
|
|
std::vector<Tree_Node*> result;
|
|
if (nodes.empty())
|
|
return result;
|
|
std::stack<Tree_Node*> stack;
|
|
for (Tree_Node * node : nodes)
|
|
{
|
|
if (node)
|
|
stack.push(node);
|
|
}
|
|
while (!stack.empty()) {
|
|
Tree_Node * node = stack.top();
|
|
stack.pop();
|
|
result.push_back(node);
|
|
// 逆序压入子节点,保证从左到右的遍历顺序
|
|
for (int i = node->sons.size() - 1; i >= 0; --i) {
|
|
stack.push(node->sons[i]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
#define ReMain (pos - total_height)
|
|
int Tree_Model::height() {
|
|
int total_height = 0;
|
|
std::stack<std::pair<Tree_Node*, int>> stack;
|
|
for (Tree_Node * node : roots)
|
|
{
|
|
if (node)
|
|
stack.push({node, 0});
|
|
}
|
|
Tree_Node * cur{};
|
|
int deep{};
|
|
while (!stack.empty()) {
|
|
auto t = stack.top();
|
|
cur = t.first;
|
|
deep = t.second;
|
|
stack.pop();
|
|
if (cur->expand) {
|
|
for (int i = cur->sons.size() - 1; i >= 0; --i) {
|
|
stack.push({cur->sons[i], deep + 1});
|
|
}
|
|
}
|
|
total_height += cur->height + space;
|
|
}
|
|
return total_height;
|
|
}
|
|
Tree_Pos get_pos(int pos, const std::vector<Tree_Node*>& roots, int space) {
|
|
int total_height = 0;
|
|
std::stack<std::pair<Tree_Node*, int>> stack;
|
|
for (Tree_Node * node : roots)
|
|
{
|
|
if (node)
|
|
stack.push({node, 0});
|
|
}
|
|
Tree_Node * cur{};
|
|
int deep{};
|
|
while (!stack.empty()) {
|
|
auto t = stack.top();
|
|
cur = t.first;
|
|
deep = t.second;
|
|
if (ReMain < cur->height) {
|
|
return Tree_Pos{cur, deep, total_height, ReMain, stack};
|
|
}
|
|
stack.pop();
|
|
if (cur->expand) {
|
|
for (int i = cur->sons.size() - 1; i >= 0; --i) {
|
|
stack.push({cur->sons[i], deep + 1});
|
|
}
|
|
}
|
|
total_height += cur->height + space;
|
|
}
|
|
return Tree_Pos{cur, deep, total_height, ReMain, stack};
|
|
}
|
|
void select_node(const std::vector<Tree_Node*>& roots, int view_y, int length, int space, Node_Call_Back call_back) {
|
|
auto ret = get_pos(view_y, roots, space);
|
|
std::stack<std::pair<Tree_Node*, int>>& stack = ret.rest;
|
|
int cur_inside_y = ret.node_pos;
|
|
int cur_inside_end = cur_inside_y + length;
|
|
while (!stack.empty()) {
|
|
auto [cur, depth] = stack.top();
|
|
stack.pop();
|
|
if (cur->expand) {
|
|
for (int i = cur->sons.size() - 1; i >= 0; --i) {
|
|
stack.push({cur->sons[i], depth + 1});
|
|
}
|
|
}
|
|
call_back(cur, depth, cur_inside_y);
|
|
cur_inside_y += cur->height + space;
|
|
if (cur_inside_y > cur_inside_end) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|