上接IL算法

7.学习完数据结构后,考虑怎么有效的进行取出的问题(问题4中提到的)。

以下是截取方式(可能不是最佳的):

1)          查找到’<’位置,位置,然后用CString类型截取出关键字。关键字取出后有冒号,需要过滤掉。注意Mid()函数的第二个参数是截取的个数

2)          找到第二个,用Mid()截取出结点的个数。截断字符串。

3)          考虑使用二重循环来遍历所有。

第一层循环是使用getline()读取每行;第二层循环是依次读取读入的这行的数据。那么就是找’.’,这样可以依次取出编号的长度,以及编号。取出编号长度,以及编号后将其存储到int型的指针中。

知识点:

String转化成int型函数  _ttoi()

最后一个数字即分号前的数,单独处理。

当当前的结点编号结束后要加入到CArray

string转换为CString, c_str()

注意:

写程序时遇到的粗心的问题:

使用while()自变量忘记自加

变量命名不规范(没有见名知意等),使得测试时花费了很多时间

什么时候该加入到CArray中,什么时候该加入到CMap

小于和小于等于问题

由于逻辑问题导致每次取的个数都不一样,这个需要细心观察

存储的长度问题,考虑是否是需要加一

全部结束后,将CArray加入到CMap中去。

刚刚开始写读函数可能会遇到各种问题,当时在读函数上用了几天的时间。由于逻辑问题,易把问题想的太复杂了。

8.左右匹配问题(重点,时间主要花费在左右匹配上了)

计算它的左右匹配的原因是距离越近,其LCA越低。

注意1:在做左右匹配时一定要保证数据保存的正确性。因此需要测试一下。

左匹配:无论是左匹配还是右匹配都使用折半查找。因为折半查找的时间复杂度是 

注意2:由于数据集中不同的关键字的结点的编号可能会相同。例如:text  tissue 同时含有7.1.2.3505.5383.5394.5407.5411

这是因为XML中的标签和及其此标签中的文本会被抽象成为不同的关键字。例如:

<note>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget the meeting!</body>

</note>

灰色区域的form John的编号相同。

在左右匹配时,必须考虑左右匹配不存在的情况。

提示:刚刚开始写左右匹配时可能会想到把左右匹配写成一个函数,但是若发现这个有点困难,何不放一放,暂且将左右匹配写为两个函数,待实现左右匹配时再将左右匹配合为一个函数即可。

9.lca(v1,v2)即找最低共同祖先


    上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

最长共同前缀的求法:根据参数(指针类型),循环访问,其数据是否相等,直到不相等,退出循环。从而得到其最长共同前缀。

写这个函数并没有什么难度。

注:在此注意的是长度的边界问题。

10. descedant(v1,v2)//返回子孙结点

上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

子孙结点的判断方法:

观察子孙结点与其祖先结点,祖先结点的编号会完全在子孙结点中出现,这样以来,可以判断其长度即可,长度长的为子孙结点,长度短的是祖先结点。

可能会有此顾虑:参数v1,v2会不会出现不是祖先和子孙的关系?

这种情况是不会存在的,如图所示:

 上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

Ben 0.1.1.2.0(与自己写的编码不太一样,但道理一样)John的左匹配是0.1.1.1.0,右匹配是0.1.2.0.0。在经过lca()后为0.1.10.1。结果肯定是祖孙关系。所以descedant(),传递的两个参数是确定的祖孙关系。

11.get_slca()找最小最低共同祖先

本函数就是调用前面的几个函数。

 上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

初始根结点u = 0,在实现时可以设为1.1

判断u的编码是否是小于x的编码

判断u是否是x的祖先,若不是祖先则加入到Result中。

u = x是包含在if(pre(u) < pre(x))中的,伪代码有规定(可能是不成文)缩进对齐的是同一级别。即:

 上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

12.写一个调用get_slca()的函数即可。

//

优化阶段

首先优化的是左右匹配,可以考虑是否是用一个函数来完成左右匹配。

解决方法使用了两个全局变量left,right,来记录的是左右匹配的位置,而不是使用指针;左匹配做完之后,右匹配的位置也就得到了。这样可以通过位置来获得左右匹配。

1.     Lca(),descendant()

优化的方法:

将返回的最低共同祖先/子孙结点的编号改为使用结点类来存储。而结点类中包含了一个指针,指向的是子孙的编号;一个int型的变量存储的是编号的长度。

2.     get_slca()

优化方法:

u的初始化的1.1改为了,第一次的求子孙的结果。减少了一步(将1.1做为祖先)。在此不做进一步的分析。当然u相应的改为了结点类型的,因为我们在加入Result中时使用的是指针型,因此在加入前设置一个指针,将结点存的值复制给指针。

将比较大小单独做一个函数进行判断,判断时所传递的参数是结点类型。且不允许修改其值。即:

int InStream::Compare(const Node &v, const Node &node)//比较大小

3.     在调用get_slca时的优化

    因为少量的结点中找量大的结点的左右匹配的时间<将量大的与量小的结点中找左右匹配时所用的时间。所以可以考虑将比较的关键字的个数进行按升序排序。然后再调用get_slca()函数。使用的是直接插入排序。

4.     释放空间

刚刚写完xmark500时仅仅只能跑一遍,这就需要进行释放空间。

上接IL算法 - 雨竹清风 - 雨竹清风的博客

 

Carray->RemoveAll(),仅仅是将Carray中的空间进行释放,而空间中的指针没有被释放掉。因此将指针进行释放,这就需要使用双层循环将Carray进行释放干净。

相应的CMap也需要在析构函数中进行释放空间。

注意:释放空间时,需要将之前不再使用的空间进行释放,若下次还会使用,则需申请一个临时的空间暂存,使用完后,将临时空间释放即可。

5.此外还可以将结点类转换为结构体。如下:

struct Node

//class Node

{

//public:

//   Node(void);

//   ~Node(void);

//public:

int length;//长度

      int *p;//指针

};

cpp文件注释掉即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值