| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1326 人关注过本帖
标题:树的数据如何储存
只看楼主 加入收藏
纯蓝之刃
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:76
帖 子:570
专家分:3727
注 册:2019-7-29
结帖率:93.75%
收藏
已结贴  问题点数:80 回复次数:1 
树的数据如何储存
我需要从一个xml文件读取数据,数据为三层树状结构,我读取数据后以什么形式存储才能实现数据的修改、删除、添加等功能。
struct A        //第一层结点
{
    属性1;
    属性2;
}

struct B        //第二层结点,有n个
{
    属性1;
    属性2;
}

struct C        //第三层结点,每个节点B下有m个
{
    属性1;
    属性2;
}

如何实现对第二层和第三层数据的操作。节点内属性的增删添改。节点个数的增删添改。

我目前将结构A下面的结构B使用list进行管理,每个结构B再建立一个list去管理结构B下面的结构C。但是感觉效率不高且操作繁琐,虽然数据目前只有三层,但后期可能增加到五六层,有没有什么好的方法给想一个。
我使用的是qt,和c++的mfc差不多,都是图形界面。通过图形界面的操作,对数据进行反写存储,我目前的结构反写删除、插入节点等操作比较复杂,是否有操作更简洁的数据存储的方法。
搜索更多相关主题的帖子: 数据 结构 三层 属性 操作 
2020-08-30 19:09
Jonny0201
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:52
帖 子:488
专家分:2603
注 册:2016-11-7
收藏
得分:80 
如果我没有理解错的话, 感觉就是很普通的树结构, 不过每一层的节点类型都不同罢了
其实你自己的方法也很不错, 差不多就是这样 :
程序代码:
struct B;
struct C;
struct A {
    T value;
    B *next;
};
struct B {
    T value;
    C *next;
};
struct C {
    T value;
};

平时写的链表 next 的类型都是一样的, 上面只不过是 next 的类型和 this 的类型不一样
我假设 A 层不可以直接访问 C 层, 需要通过 B 层作为中介. 那么 A 映射到 B, B 下面是 C. 那么可以用标准库提供的 map, 我想应该用 std::unordered_map
using head_type = std::unordered_multimap<volatile A, std::unordered_multimap<volatile B, C>>;
这样就免去了自己写插入删除的麻烦. 但是缺点就是所有标准库提供的 map 中 key_type 默认带有 const 属性, 所以需要加一个 volatile, 方便修改
但是由于后期会增加层数, 所以类似于这种类型 std::unordered_multimap<volatile A, std::unordered_multimap<volatile B, std::unordered_multimap<volatile C, D>>> 会越写越长. 考虑元编程, 可以在写别名的时候少写一些 :
程序代码:
#include <iostream>
#include <unordered_map>

using namespace std;
template <typename ...>
struct map_type;
template <typename ...Ts>
using map_t = typename map_type<Ts...>::type;
template <typename T, typename U>
struct map_type<T, U> {
    using type = std::unordered_multimap<add_volatile_t<T>, U>;
};
template <typename T, typename U, typename ...Ts>
struct map_type<T, U, Ts...> {
    using type = std::unordered_multimap<add_volatile_t<T>, map_t<U, Ts...>>;
};
struct A {};
struct B {};
struct C {};
struct D {};
struct E {};
struct F {};
int main(int argc, char *argv[]) {
    cout << is_same_v<map_t<A, B, C>, std::unordered_multimap<volatile A, std::unordered_multimap<volatile B, C>>> << endl;       //true
    cout << is_same_v<map_t<A, B, C, D, E, F>, std::unordered_multimap<volatile A, std::unordered_multimap<volatile B, std::unordered_multimap<volatile C, std::unordered_multimap<volatile D, std::unordered_multimap<volatile E, F>>>>>> << endl;      //true
}

只要能够表示出来, 图像界面操作不在话下

这是考虑每一层的节点类型中的成员都不太一样的情况下, 如果可以保证每一个节点类型中有相同的成员, 就可以考虑写一个普通的树 :
程序代码:
template <typename T>
struct tree_node {
    T value;
    tree_node **next;
    size_t next_size;
    tree_node *previous;
};
template <typename Node, bool IsConst>
class tree_iterator;
template <typename T, typename Allocator>
class tree {
public:
    //部分别名例如 value_type, reference 等此处删除
    //...
    using iterator = tree_iterator<tree_node<T>, false>;
    using const_iterator = tree_iterator<tree_node<T>, true>;
public:
    void insert_under(const_iterator pos, const T &value);    //在某一个节点下插入一个新的节点, 当然这是默认插在最后, 可以再给一个重载插入到指定位置
    void erase_under(const_iterator pos, size_t n);
};

因为 tree 只接受一个类型, 所以借助 std::variant 进行类型擦除即可 :
using tree_t = tree<std::variant<A, B, C, D, E, F>>;
甚至干脆一点, 直接用 void * 进行类型擦除

个人意见仅供参考, 你的想法已经比较简单了, 而且实现起来也不会特别难

[此贴子已经被作者于2020-8-31 02:14编辑过]

2020-08-31 02:10
快速回复:树的数据如何储存
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016255 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved