我和我的输入提示--树结构

/*
encoding:gbk
	简记: 输入提示的最核心的树节点的结构

该结构默认做了几个限制:
	1. 数据的属性为两个字节
	2. 字符串的长度最长为255(包含前缀部分)
	3. 数据的权重范围为10bit(0-1023)
	4. 数据量最好不要超过一亿(最好千万以内)->要处理千万或亿甚至更多则需要分割
	5. 数据的扩展部分最好在总大小1G以内(一般会远远小于该值的)

qq: 315753857
*/

#ifndef _XH_TREE_STRUCT_H_
#define _XH_TREE_STRUCT_H_
#include <cstring>

//是否压缩节点
#define _NOT_WITH_COMPACK_ST_ 0

//可以压缩的结点的个数
#define CAN_COMPACK_NOOD_NUMBER 5

//节点权重的最大值[权重范围0-1023]
#define MAX_WEIGHT_CHINESE     0x3ff

//XHRbNode->usHua使用
//XH_TREE_HUA_INFO_WIFE  -> 是否具有wife
//XH_TREE_HUA_INFO_MID   -> 是否具有中间孩子
//XH_TREE_HUA_INFO_LEFT  -> 是否具有左孩子
//XH_TREE_HUA_INFO_RIGHT -> 是否具有右孩子
//XH_TREE_HUA_INFO_SSELF -> 是否具有spellself->指向自己本身的结构信息
#define XH_TREE_HUA_INFO_WIFE  0x01
#define XH_TREE_HUA_INFO_MID   0x02
#define XH_TREE_HUA_INFO_LEFT  0x04
#define XH_TREE_HUA_INFO_RIGHT 0x08
#define XH_TREE_HUA_INFO_SSELF 0x10

//获取偏移位置                                 // 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
const static unsigned char g_sucCompackPos[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};

//社会病态,只关心孩子不关系父母
//用于查询使用的红黑树(简化版)
//该结构有几点需要注意
//1. left,mid,right指向的是地址,不是数组下标
//2. 最终索引里面,可能data,mid,left,right,ss(spellself)并不全存在,为了节省空间
//3. 存储树节点时,不要从0地址开始,因为0地址是有意义的,代表没有内容
typedef struct _XHRbNode {
    char cByteDif;             //不同字节的内容
    unsigned char cPosDif;     //不同字节的位置

    unsigned short usWPeer:1;     //是否有成对的信息节点存在(跟当前节点字母忽略大小写,字母一样的节点)
    unsigned short usHua:5;       //具有多种信息->具体见XH_TREE_HUA_INFO_XXXX
    unsigned short usWeight:10;   //节点的权重

    //下面几个节点都可能会被压缩
    unsigned int  uiWife;      //节点的数据部分
    unsigned int  uiMid;       //中孩子  ----中孩子放到左孩子前面,因为中孩子需要去数据访问多
    unsigned int  uiLeft;      //左孩子
    unsigned int  uiRight;     //右孩子
    unsigned int  uiSpellSelf; //全拼位置 ->为了加速简拼全拼混合查询速度而生的,指向自身全拼所对应的位置

public: //接口
    _XHRbNode () {
        memset(this, 0x00, sizeof(struct _XHRbNode));
    };
	//压缩的准备,预处理
    void ComposeCut() {
#if _NOT_WITH_COMPACK_ST_ 
        return ;
#endif
        int iPos = 0;
        if(usHua & XH_TREE_HUA_INFO_WIFE)   iPos++;
        if(usHua & XH_TREE_HUA_INFO_MID)    (&uiWife)[iPos++] = uiMid;
        if(usHua & XH_TREE_HUA_INFO_LEFT)   (&uiWife)[iPos++] = uiLeft;
        if(usHua & XH_TREE_HUA_INFO_RIGHT)  (&uiWife)[iPos++] = uiRight;
        if(usHua & XH_TREE_HUA_INFO_SSELF)  (&uiWife)[iPos++] = uiSpellSelf;
    };
    //下面几个函数是查询时使用,因为查询的时候,为了减少内存的消耗,对数据结构进行了压缩
    //把左中右孩子、数据部分在没有的情况进行了去除。因此这四个字段,只有在有的情况下才表示
    unsigned int UncomposeWife() const { //因为数据部分用到的多,因此放到了前面
        if(!(usHua & XH_TREE_HUA_INFO_WIFE)) return 0;
        return uiWife;
    };
    unsigned int UncomposeMid() const {
        if(!(usHua & XH_TREE_HUA_INFO_MID)) return 0;
#if _NOT_WITH_COMPACK_ST_ 
        return uiMid;
#endif
        return (&uiWife)[bWife];
    };
    unsigned int UncomposeLeft() const {
        int iTmp = usHua & XH_TREE_HUA_INFO_LEFT;
        if(!iTmp) return 0;
#if _NOT_WITH_COMPACK_ST_ 
        return uiLeft;
#endif
        return (&uiWife)[g_sucCompackPos[(iTmp - 1) & usHua]];
    };
    unsigned int UncomposeRight() const {
        int iTmp = usHua & XH_TREE_HUA_INFO_RIGHT;
        if(!iTmp) return 0;
#if _NOT_WITH_COMPACK_ST_ 
        return uiRight;
#endif
        return (&uiWife)[g_sucCompackPos[(iTmp - 1) & usHua]];
    };
    unsigned int UncomposeSpellSelf() const {
        int iTmp = usHua & XH_TREE_HUA_INFO_SSELF;
        if(!iTmp) return 0;
#if _NOT_WITH_COMPACK_ST_ 
        return uiSpellSelf;
#endif
        return (&uiWife)[g_sucCompackPos[(iTmp - 1) & usHua]];
    };
    unsigned int GetComposeSize() { //获取压缩后的大小
        unsigned int uiSize = sizeof(_XHRbNode);
#if _NOT_WITH_COMPACK_ST_ 
        return uiSize;
#endif
        unsigned int uiT = g_sucCompackPos[usHua & (XH_TREE_HUA_INFO_SSELF - 1)] + ((usHua & XH_TREE_HUA_INFO_SSELF) ? 1 : 0);
        return uiSize - (CAN_COMPACK_NOOD_NUMBER - uiT) * sizeof(unsigned int);
    };
}XHRbNode;

//ucAttr的意义
#define FLAG_CHINESE_UCATTR_WITHEXTRAINFO  1  //含有扩展信息
//_XHChineseData 与 _XHSpellData的大小需要一致(为了更方便)
typedef struct _XHChineseData {
    unsigned short usWeight:10;  //汉字的权重

    //ucAttr: 1 1 1 1 1 1 //目前还有5位扩展
    //                  |
    //                 \|/
    //                  是否含有扩展信息 0x01
    unsigned short usAttr:6;      //字节属性   -->自身具备(是否具有dot属性)
    unsigned short usAttr;        //双字节属性 -->外部设置
    //数据部分的位置->汉字的字符串部分是区分与spelldata的字符串部分的,因为汉字的字符串部分还受FLAG_CHINESE_UCATTR_WITHEXTRAINFO的影响
    //当FLAG_CHINESE_UCATTR_WITHEXTRAINFO为1的时候,uiStringPos指向的位置往前4个字节为一个数字。这个数字指向扩展信息的位置
    unsigned int uiStringPos;
}XHChineseData;

typedef struct _XHSpellData {
    //是否含有多个结果,这个主要是用于中间汉字,因为中间拼音存储了上级中间汉字的编号,
    //要通过中间汉字去汉字里面查找结果,因此中间拼音需要知道中间汉字是否对应多个结果
    unsigned int bMD:1;  //只有中间汉字需要
    //两层含义: 
    //1. 当bMD为0 代表该节点指向的上级数据只有一个,因此直接就是uiUpperPos
    //2. 当bMD为1 代表该节点指向的上级数据有多个,那么uiUpperPos则为这多个数据里面的第一个数据的位置,往前4个字节则是上级数据总共的个数
    unsigned int uiUpperPos:31;
    unsigned int uiStringPos; //指向字符串的内容
}XHSpellData;

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值