首页 > 编程语言 >TreeCtrl 树的存储和还原 2, VC++

TreeCtrl 树的存储和还原 2, VC++

时间:2023-07-31 14:15:12浏览次数:40  
标签:map 存储 pid list C++ TreeCtrl len sid id

TreeCrtl树的节点可以随意的添加,删除,移动。树保存到数据库中,并能从数据库读出还原。

树节点的LPARAM存放ID,这个ID是数据表自增长主键。

1.数据库中读出,按PID,SID顺序,这样读出的第一个为root
2.读出的数据存入list
3.创建root节点,把root放入map,从list中删除
4.遍历list,pid,sid 在map中找到,说明符合创建条件,创建后,把节点从list中移进map
5.继续遍历list,直到list中没有元素。

树已经建好,清空map,list。

好处:

1.树结存储的结构数据是 id,pid,sid,和树结构的逻辑关系完全一致
2.树结构改动,只需更新数据库中相邻节点的结构数据,更新量少
3.树中不需要保存额外的结构数据。

缺点:
重建时,从数据库中读出的节点数据顺序是随机的。无法按记录顺序创建树。
需要循环遍历list找到可以创建的节点,顺序创建。
.

总结:
比之前的利用层数据和遍历序号存储还原要好,树结构越大性价比越高,增加内存操作减少磁盘IO。

 

树的存储方式:

 树的还原:

 树节点对应的内容是foreign ID 关联的另一张表的Blob字段。

主要的树的还原程序段:

1。

HTREEITEM CPNotesTree::AddNode(LPARAM lParam, int image, int imageselected, wchar_t* szText, HTREEITEM hParent, HTREEITEM hAfter)
{
    TVINSERTSTRUCT tvins;
    TVITEM tvi;

    tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; // 
    tvins.item.pszText = szText;
    tvins.item.iImage = image;          //初始图标都是文件 
    tvins.item.iSelectedImage = imageselected;
    tvins.item.lParam = lParam;
    tvins.hParent = hParent;
    tvins.hInsertAfter = hAfter;
   
    return (HTREEITEM)SendMessage(m_hWndTree, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
}

void CPNotesTree::ShowNotesTree()
{
    int nrow, ncolum;
    int i, j;

    char* p = NULL;
    int p_len =0;
    int len = 0;

    DeleteTreetView();
        //非动态修改的用const不占用堆栈,
    char* sql = "select id,pid,sid,name from notestree order by pid, sid";  //order 保证第一个是root

    m_pSQLite = &m_SQLite;
    m_pSQLite->Query(sql, nrow, ncolum);
    
    HTREEITEM  hParent = NULL;
    HTREEITEM  hAfter = NULL; //Sibling 
    HTREEITEM  hCurrent = NULL;

    //HTREEITEM hRoot = m_wndFileView.GetSelectedItem(); //插入节点
    //HTREEITEM hRoot = m_hNotes;

    HTREEITEM hRoot = NULL;

    struct ST_TN
    {
        UINT32 type;
        UINT32 id;
        UINT32 pid;
        UINT32 sid;
        wchar_t wname[256];   //数据库中的UTF8转化层UTF16
    }tn;

    list<ST_TN> ltn;  //list 中是没有插入的节点
    list<ST_TN>::iterator it_list;
    list<ST_TN>::iterator it_list2;  //副本用来删除时保证右移
        
    map<int, HTREEITEM> DataMap;   //map 中是已经插入的节点
    map<int, HTREEITEM>::iterator it_map_pid;  //迭代器,用于查找
    map<int, HTREEITEM>::iterator it_map_sid;  
    
    ltn.clear();

    for (i = 1; i < nrow + 1; i++)    //第一行是字段名称
    {
        tn.id = atoi(m_pSQLite->m_sresult[i * ncolum + 0]);
        tn.pid = atoi(m_pSQLite->m_sresult[i * ncolum + 1]);
        tn.sid = atoi(m_pSQLite->m_sresult[i * ncolum + 2]);
                
        p = m_pSQLite->m_sresult[i * ncolum + 3];
        p_len = strlen(p);

        len = MultiByteToWideChar(CP_UTF8, 0,p,p_len,NULL, 0);  //用UTF8 保存在数据库中
        if (len > 255) len = 255;  //别溢出了
        MultiByteToWideChar(CP_UTF8, 0, p, p_len, tn.wname, len);
        tn.wname[len] = '\0';
        ltn.push_back(tn); //第一个是root
    }

    //root
    hParent = hRoot;
    hAfter = hRoot;

    it_list = ltn.begin();

    hCurrent = AddNode((LPARAM)it_list->id, 0, 0, it_list->wname, hParent, hAfter);  
    DataMap.insert(pair<int, HTREEITEM>(it_list->id, hCurrent));  //插入后到的句柄和id成对保存到map
    ltn.erase(it_list);

    while (ltn.size())  //直到List中的节点全部移走
    {
        it_list = ltn.begin();
        while (it_list!= ltn.end())  //遍历List
        {
            it_map_pid = DataMap.find(it_list->pid);
            hParent = (it_map_pid == DataMap.end())?NULL: it_map_pid->second;
            
            if (it_list->sid == 0)
            {
                hAfter = TVI_FIRST;
            }
            else
            {
                it_map_sid = DataMap.find(it_list->sid);
                hAfter = (it_map_sid == DataMap.end()) ? NULL : it_map_sid->second;
            }
            
            if ((hParent != NULL) && (hAfter != NULL))
            {
                hCurrent = AddNode((LPARAM)it_list->id, 0, 0, it_list->wname, hParent, hAfter);  //type4 notes 数据结构
                //处理节点数据:可以用list扩展,id换成pos作为索引
                DataMap.insert(pair<int, HTREEITEM>(it_list->id, hCurrent));  //插入后到的句柄和id成对保存到map
                
                it_list2 = it_list;  //list 删除用迭代器位置的元素后,当前迭代器不能继续遍历,要用副本进行删除。
                it_list++;
                ltn.erase(it_list2);
             }
            else
            {
                it_list++;
            }
        }
    }
    ltn.clear();
    DataMap.clear();  //树构造完后清除map,若保留则树改变时也要维护map
    ExpandAll(TreeView_GetRoot(m_hWndTree));
}

 

标签:map,存储,pid,list,C++,TreeCtrl,len,sid,id
From: https://www.cnblogs.com/xgz21/p/17593257.html

相关文章

  • mysql 存储过程 插入数据 id自增
    MySQL存储过程插入数据id自增概述在MySQL中,存储过程是一种事先编译好的SQL语句集合,可以通过存储过程来简化开发流程、提高性能和重复使用性。当需要插入数据并自动生成自增的id时,可以使用存储过程来实现。本文将教你如何使用MySQL存储过程来插入数据,并使id字段自增......
  • mysql 存储富文本类型
    MySQL存储富文本类型在Web开发中,经常需要存储和处理富文本数据,例如文章内容、博客内容、评论等。MySQL作为一种常用的关系型数据库管理系统,提供了多种数据类型来存储不同的数据。本文将介绍如何在MySQL中存储和处理富文本类型数据,并提供相应的代码示例。1.富文本数据类型选择My......
  • mysql 创建存储过程,查询某学号学生计算机基础课的成绩 ,并输出“优秀”或“良好
    MySQL存储过程简介及示例什么是存储过程?存储过程是一段预编译的SQL代码,可以在数据库中被重复使用。通过存储过程,我们可以将一系列的SQL语句组合在一起,并进行参数的传递和逻辑控制,从而提高数据库的性能和安全性。MySQL存储过程的创建在MySQL中,我们可以使用CREATEPROCEDURE语句......
  • 从 C++到 Objective-C ----2
    从C++到Objective-C(7):继承简单继承Objective-C也有继承的概念,但是不能多重继承。不过,它也有别的途径实现类似多重继承的机制,这个我们后面会讲到。C++Objective-CclassFoo:publicBar,{}@interfaceFoo:Bar//单继承//如果要同时“继承”Wiz,需要使用......
  • 从 C++ 到Objective-C
    从C++到Objective-C(1):前言DevBean 日期:2011年03月18日Objective-C可以算作Apple平台上“唯一的”开发语言。很多Objective-C的教程往往直接从Objective-C开始讲起。不过,在我看来,这样做有时候是不合适的。很多程序员往往已经掌握了另外一种开发语言,如果对一门新......
  • Name Mangling and extern “C” in C++
    SinceC++supportsfunctionoverloading,additionalinformationhastobeaddedtofunctionnames(calledNamemangling)toavoidconflictsinbinarycode.2.FunctionnamesmaynotbechangedinCasitdoesn'tsupportfunctionoverloading. Toavoid......
  • python 接口返回存储json字符串包含\n
    实现“python接口返回存储json字符串包含\n”的步骤为了实现接口返回存储包含特殊字符\n的JSON字符串,我们需要按照以下步骤进行操作:步骤描述1创建一个Python接口2生成包含特殊字符\n的JSON字符串3返回JSON字符串现在,让我们一步步实现这个过程。步骤1:创建......
  • 数据库行存储索引与列存储索引
          行存储是在逻辑上整理为包含行和列的表,实际上以行式数据格式存储的数据,此格式是存储关系表数据的传统方法。列存储是在逻辑上整理为包含行和列的表,实际上以列式数据格式存储的数据。   行存储索引最适合用于查找数据、搜索特定值的查询,或者针对较小范围的值......
  • C++11新特性
    一.智能指针1.std::shared_ptrshared_ptr使用了引用计数,每一个shared_ptr的拷贝都指向相同的内存,每次拷贝都会触发引用计数+1,每次生命周期结束析构的时候引用计数-1,在最后一个shared_ptr析构的时候,内存才会释放。2.std::weak_ptrweak_ptr是用来监视shared_ptr的生命周......
  • 代码随想录-哈希表-c++总结
    哈希表内容整体简单,关键是要有利用map映射的思想,以及巩固一些c++标准库的操作这次三数之和一题没有直接做出来,关键在于如何查重一点比较绕15.三数之和-力扣(LeetCode)利用排序+双指针解决三数之和的思路更加清楚此外,四数之和中,四个数相加会溢出int,应改为 ......