分享
 
 
 

编程手记之ANSI C篇-(三)二叉分析树

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

二叉树因有规范和确定性的结构而得到广泛的应用,在每个树节点中,有两个子二叉树,通常称为孩子节点和兄弟节点。在我的应用中,要将二叉树应用于文档分析,文档是一个嵌套的子项目集合,每个项目都有其特定的属性,文档最终分析的结果是一个树型结构的项目视图。根据这一要求,我需要在节点中维护一个基于命名属性的动态属性表以存储项目的不同的属性,属性表由哈希表实现,且看设计如下:

1、定义二叉树:

/*二叉树的宿主的结构*/

typedef struct tagTreeData{

LINK lkItems; /*宿主的根连接件,维护二叉树的根节点*/

LINK lk; /*宿主的自身连接件*/

}TreeData;

/*二叉树节点的结构*/

typedef struct tagTreeItem{

LINK lkChild; /*孩子节点的根连接部件*/

LINK lkSibling; /*自身连接件,作为父节点间兄弟节点的连接之用*/

LINKPTR pht; /*该节点的属性表*/

int nChildCount; /*子节点的计数*/

unsigned long data; /*节点的长整型数值*/

}TreeItem;

/*定义节点数据标识*/

#define lkTreeData 21

#define lkTreeItem 22

/*定义属性表的哈希表的模基为7*/

#define MIN_ITEM 7

/*从宿主连接件指针中恢复宿主数据*/

#define TreeDataFromLink(p) ((TreeData*)((unsigned int)p - (unsigned int)&(((TreeData*)0)->lk)))

/*从宿主根连接件指针中恢复宿主数据*/

#define TreeDataFromChild(p) ((TreeData*)((unsigned int)p - (unsigned int)&(((TreeData*)0)->lkItems)))

/*从节点连接件指针中恢复节点数据*/

#define TreeItemFromLink(p) ((TreeItem*)((unsigned int)p - (unsigned int)&(((TreeItem*)0)->lkSibling)))

/*从节点孩子节点的根连接件指针中恢复节数据*/

#define TreeItemFromChild(p) ((TreeItem*)((unsigned int)p - (unsigned int)&(((TreeItem*)0)->lkChild)))

2、二叉分析树的操作实现:

/*创建二叉树*/

LINKPTR CreateTreeData(void)

{

TreeData* ptd = (TreeData*)calloc(1,sizeof(TreeData));

ptd->lk.tag = lkTreeData;

/*初始化根连接部件*/

InitRootLink(&ptd->lkItems);

return &(ptd->lk);

}

/*销毁二叉树

ptr: 二叉树连接部件*/

void DestroyTreeData(LINKPTR ptr)

{

TreeData* ptd;

assert(ptr);

assert(ptr->tag == lkTreeData);

ptd = TreeDataFromLink(ptr);

/*清除宿主中的所有节点*/

ClearTreeData(ptr);

free(ptd);

}

/*清除宿主中的所有节点

ptr: 二叉树连接部件*/

void ClearTreeData(LINKPTR ptr)

{

TreeData* ptd;

LINKPTR ilk,pre;

assert(ptr);

assert(ptr->tag == lkTreeData);

ptd = TreeDataFromLink(ptr);

ilk = GetFirstLink(&ptd->lkItems);

while(ilk)

{

pre = ilk;

ilk = GetNextLink(ilk);

/*删除该节点以及该节点的子节点*/

DeleteTreeDataItem(ptr,pre);

}

}

/*删除该节点以及该节点的子节点

ptrTree: 二叉树连接件指针

ptrItem: 待删除的节点连接件指针*/

void DeleteTreeDataItem(LINKPTR ptrTree,LINKPTR ptrItem)

{

LINKPTR parent,ilk,pre;

TreeItem* ptt;

TreeItem* pup;

TreeData* ptd;

assert(ptrTree);

assert(ptrTree->tag == lkTreeData);

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

/*删除子节点*/

ilk = GetFirstLink(&ptt->lkChild);

while(ilk)

{

pre = ilk;

ilk = GetNextLink(ilk);

DeleteTreeDataItem(ptrTree,pre);

}

/*销毁该节点的属性表*/

DestroyHashTable(ptt->pht);

/*取得该节点的父节点的连接件指针*/

parent = GetTreeDataParentItem(ptrItem);

if(parent)

{

/*父节点存在,则从父节点的子节点链表中删除该节点*/

pup = TreeItemFromLink(parent);

DeleteLinkAt(&(pup->lkChild),ptrItem);

pup->nChildCount --;

}else

{

/*父节不存在,说明该节点是根节点,则从宿主的根节点链表中删除该节点*/

ptd = TreeDataFromLink(ptrTree);

DeleteLinkAt(&(ptd->lkItems),ptrItem);

}

/*释放节点*/

free(ptt);

}

/*在父节点中插入一个新的子节点

ptrTree: 二叉树连接件指针

parent: 父节点连接件指针

pos: 待插入的位置,可以为LINK_LAST、LINK_FIRST或某一已经存在于链表中的指针*/

LINKPTR InsertTreeDataItem(LINKPTR ptrTree,LINKPTR parent,LINKPTR pos)

{

TreeItem* ptt;

TreeItem* pup;

TreeData* ptd;

assert(ptrTree);

assert(ptrTree->tag == lkTreeData);

/*新建一个节点*/

ptt = (TreeItem*)calloc(1,sizeof(TreeItem));

InitRootLink(&ptt->lkChild): /*初始化该节点孩子节点的根连接件*/

ptt->lkSibling.tag = lkTreeItem;

ptt->pht = CreateHashTable(MIN_ITEM); /*创建属性表*/

if(parent == NULL)

{

/*父节点为空,则插入到根节点链表中*/

ptd = TreeDataFromLink(ptrTree);

InsertLinkAt(&(ptd->lkItems),pos,&(ptt->lkSibling));

}else

{

/*父节点存在,则插入到他的孩子节点链表中*/

pup = TreeItemFromLink(parent);

InsertLinkAt(&(pup->lkChild),pos,&(ptt->lkSibling));

pup->nChildCount ++;

}

/*返回该节点的连接件指针*/

return &(ptt->lkSibling);

}

/*取得节点的孩子节点计数

ptrItem: 节点的连接件指针*/

int GetTreeDataChildItemCount(LINKPTR ptrItem)

{

TreeItem* ptt;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

return ptt->nChildCount;

}

/*取得第一个孩子节点的连接件指针

ptrItem: 当前节点连接件指针*/

LINKPTR GetTreeDataChildItem(LINKPTR ptrItem)

{

TreeItem* ptt;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

return GetFirstLink(&ptt->lkChild);

}

/*取得父亲节点的连接件指针

ptrItem: 当前节点连接件指针*/

LINKPTR GetTreeDataParentItem(LINKPTR ptrItem)

{

TreeItem* ptt;

LINKPTR parent;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

/*取得该节点所在的根连接件指针*/

parent = GetRootLink(ptrItem);

assert(parent);

/*从孩子根连接件指针中恢复父节点数据*/

ptt = TreeItemFromChild(parent);

if(ptt->lkSibling.tag == lkTreeItem)

return &(ptt->lkSibling); /*该节点是一个数据节点*/

else

return NULL; /*该节点是一个根节点*/

}

/*取得后续兄弟节点的连接件指针

ptrItem: 当前节点的连接件指针*/

LINKPTR GetTreeDataNextSiblingItem(LINKPTR ptrItem)

{

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

return GetNextLink(ptrItem);

}

/*取得前趋兄弟节点的连接件指针

ptrItem: 当前节点的连接件指针*/

LINKPTR GetTreeDataPrevSiblingItem(LINKPTR ptrItem)

{

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

return GetPrevLink(ptrItem);

}

/*取得宿主中第一个根节点的连接件指针

ptrItem: 宿主连接件指针*/

LINKPTR GetTreeDataRootItem(LINKPTR ptrTree)

{

TreeData* ptd;

assert(ptrTree);

assert(ptrTree->tag == lkTreeData);

ptd = TreeDataFromLink(ptrTree);

return GetFirstLink(&ptd->lkItems);

}

/*设置节点的属性

ptrItem: 节点的连接件指针

szKey: 属性名称

keylen: 属性名称长度

szVal: 属性值

valen: 属性值长度*/

void WriteTreeDataItemProper(LINKPTR ptrItem,TCHAR* szKey,int keylen,TCHAR* szVal,int vallen)

{

TreeItem* ptt;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

/*添加属性至属性表*/

AddHashEntry(ptt->pht,(TCHAR*)szKey,keylen,(TCHAR*)szVal,vallen);

}

/*由属性名称检索属性值

ptrItem: 节点连接件指针

szKey: 属性名称

buf: 拷贝区

max: 拷贝区的最大字符数*/

int ReadTreeDataItemProper(LINKPTR ptrItem,const TCHAR* szKey,TCHAR* buf,int max)

{

TreeItem* ptt;

LINKPTR elk;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

assert(buf && max >= 0);

ptt = TreeItemFromLink(ptrItem);

/*查找哈希表,是否有匹配的键*/

elk = GetHashEntry(ptt->pht,(TCHAR*)szKey,-1);

if(elk == NULL)

{

buf[0] = _T('\0');

return 0;

}else

{

return GetHashEntryVal(elk,buf,max);

}

}

/*由属性名称检索属性值字符串的指针

ptrItem: 节点连接件指针

szKey: 属性名称*/

TCHAR* GetTreeDataItemProperPtr(LINKPTR ptrItem,const TCHAR* szKey)

{

TreeItem* ptt;

LINKPTR elk;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

assert(buf && max >= 0);

ptt = TreeItemFromLink(ptrItem);

/*查找哈希表,是否有匹配的键*/

elk = GetHashEntry(ptt->pht,(TCHAR*)szKey,-1);

if(elk == NULL)

{

return NULL;

}else

{

return GetHashEntryValPtr(elk);

}

}

/*由属性名称检索属性值字符串的长度

ptrItem: 节点连接件指针

szKey: 属性名称*/

int GetTreeDataItemProperLength(LINKPTR ptrItem,const TCHAR* szKey)

{

TreeItem* ptt;

LINKPTR elk;

TCHAR* tmp;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

/*查找哈希表,是否有匹配的键*/

elk = GetHashEntry(ptt->pht,(TCHAR*)szKey,-1);

if(elk == NULL)

return 0;

else

{

tmp = GetHashEntryValPtr(elk);

if(tmp == NULL)

return 0;

else

return _tcslen(tmp);

}

}

/*取得节点的长整型值

ptrItem: 节点连接件指针*/

unsigned long GetTreeDataItemData(LINKPTR ptrItem)

{

TreeItem* ptt;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

return ptt->data;

}

/*设置节点的长整型值

ptrItem: 节点连接件指针*/

void SetTreeDataItemData(LINKPTR ptrItem,unsigned long data)

{

TreeItem* ptt;

assert(ptrItem);

assert(ptrItem->tag == lkTreeItem);

ptt = TreeItemFromLink(ptrItem);

ptt->data = data;

}

3、由于树节点内置了动态属性表,增强了二叉分析树的通用性,在接下来的XML文档的解析自动机中,将有用武之地。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有