`
touchmm
  • 浏览: 1038060 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

优化——使用“二分法”快速建立数据树

阅读更多

标题:优化——使用“二分法”快速建立数据树

内容:

父子节点的数据量上万,花了一个晚上的时间对建树的算法做了优化。

比用循环查找父节点来建树的速度快多了。 ^_^

谨记之。


备注:对数据表中父子节点的数据如下形式的可以使用本算法。

DID PID FLMC
1 0 A
2 0 B
3 0 C
4 1 A1
5 1 A2
6 2 B1
7 2 B2
8 3 C1
9 3 C1
10 4 A11
11 4 A12


{====================================================================
功 能: 定义结构体,用来保存所有非叶子节点的DID和节点的唯一句柄。
节点的句柄用来查找节点。
Treeview.Items.GetNode(Handle)可以得到该节点。

备 注: HTreeItem的定义需要Uses Commctrl。

日 期: 2006/01/16 by JRQ
=====================================================================}

Uses Commctrl;

type
PTree_Node=^TTree_Node;
TTree_Node=record
DID : Integer; //非叶子节点的DID
Handle : HTreeItem; //非叶子节点的句柄
end;

var MyNode: PTree_Node; //自定以结构

{====================================================================
功 能: 使用“二分法”创建父子节点树。
通过TList保存数据表中所有的非叶子节点的序号和句柄。
然后遍历数据表中的数据一次即可生成树。
遍历数据时,需要确定此数据的父节点,此时使用二分法在TList中查找。
使用两分法搜索节点,比循环搜索父节点速度快,这是提高效率的基础。
当树的深度和广度的数值都较大时,其优越性尤为明显。

备 注: 2006/01/16 by JRQ
=====================================================================}

procedure BuildFLBTree(aTreeview: TTreeview; //对象树
Root:TTreeNode; //顶级根节点
aQuery:TADOQuery); //查询数据集

//GetDIDIndex为二分查找实现函数
function GetDIDIndex(aList:TList; nStart,nEnd:Integer; aDID:Integer):Integer;
var i:integer;
StartNode,EndNode:PTree_Node;

begin
Result:=-1;
if nEnd<nStart then
Exit;

StartNode:= aList.Items[nStart]; //起始
EndNode:= aList.Items[nEnd]; //末尾

if (nEnd=nStart) then
begin
if EndNode.DID =aDID then
Result:=nEnd; //返回非叶子节点的Index
Exit;
end;

if (aDID < StartNode.DID) or (aDID > EndNode.DID) then
Exit;

i:=((nStart+nEnd) shr 1); //右移动一位,相当于除以2

MyNode:= aList.Items[i];
if aDID = MyNode.DID then
Result:=i //找到非叶子节点的Index
else
if aDID > MyNode.DID then
Result:=GetDIDIndex(aList,i+1,nEnd,aDID)
else
if aDID < MyNode.DID then
Result:=GetDIDIndex(aList,nStart,i,aDID);
end;

var
i,PIDCount,aDID,aPID:Integer;
sName:String;
aNode:TTreeNode; //树节点
aList:TList;
begin
aList:=TList.Create;
try
with aQuery do
begin
Close;
SQL.Clear;
//检索非叶子节点的DID,这些DID都保存在PID中(除0以外的PID中保存的是全部非叶子节点的DID)
SQL.Add('Select PID From CLASSIFY Where PID<>''0'' Group By PID Order By PID ');
Open;

First;

//取出所有非叶子节点的DID,然后保存在List中,因为这些节点可能会重复使用。
//PID为0的节点是顶层节点。除0以外的PID中保存的是全部非叶子节点的DID。
while Not(Eof) do
begin
aPID:=FieldbyName('PID').AsInteger;

New(MyNode); //生成一个节点的记录
MyNode.DID:=aPID;
MyNode.Handle:=nil; //初试化 Handle 值为空
aList.Add(MyNode);
Next;
end; //while Not(Eof) do

PIDCount:=aList.Count; //保存TList中所有非叶子节点的个数

Close;
SQL.Clear;

//查询数据表中所有的父子节点记录,以PID和DID排序,这点非常重要。
//以PID和DID排序,这样能保证所有在树上的父节点都比子节点早建立。
SQL.Add('Select DID,PID,FLMC From D_CLASSIFY Order By PID,DID ');
Open;

First;

while Not(Eof) do //遍历一次查询结果,找到每个节点的根节点,然后构建父子节点树。
begin
aDID:=FieldbyName('DID').AsInteger;
aPID:=FieldbyName('PID').AsInteger;
sName:=Trim(FieldbyName('FLMC').AsString);

if (aPID=0) then //处理第一层根节点,第一层根节点其PID为0。
begin
aNode:=aTreeview.Items.AddChild(Root,sName); //添加节点
aNode.ImageIndex:= 0; //添加图标
aNode.SelectedIndex:= 1;

i:=GetDIDIndex(aList,0,PIDCount-1,aDID); //找到根节点,为其 Handle 赋值
if i>=0 then
Ptree_Node(aList.Items[i]).Handle:= aNode.ItemId; //为List中找到的节点的Handle赋值
end
else
begin //处理非第一层的节点
i:=GetDIDIndex(aList,0,PIDCount-1,aPID); //找到根节点的位置

//通过Handle在目录树上找到根节点
aNode:=aTreeview.Items.GetNode(Ptree_Node(aList.Items[i]).Handle);

if aNode<>nil then
begin
aNode:=aTreeview.Items.AddChild(aNode,sName); //将本节点添加到找到的根节点上
aNode.ImageIndex:= 0; //添加图标
aNode.SelectedIndex:= 1;
end;

i:=GetDIDIndex(aList,0,PIDCount-1,aDID); //在List中找本节点,判断本节点是否存在List中。

if i>=0 then //如果本节点在List中存在,则本节点还有下级节点。

//为List中找到的节点的 Handle赋值
PTree_Node(aList.Items[i]).Handle:= aNode.ItemId;

end;
Next;
end; //while Not(Eof) do
end;//with aQuery do

finally

//释放节点
for i:=0 to alist.Count-1 do
begin
MyNode:=alist.Items[i];
if MyNode<>nil then
Dispose(MyNode); //释放
end;
FreeAndNil(aList);//释放
end;
end;

-完-

By JRQ

2006/02/20 于穗

分享到:
评论

相关推荐

    ASP.NET源码——顺序表字典二分法逐级检索.zip

    在这个“ASP.NET源码——顺序表字典二分法逐级检索.zip”压缩包中,包含了一个具体的源码实现,该实现可能是一个搜索引擎或数据检索系统,使用了顺序表、字典和二分查找算法来提高检索效率。 首先,我们要理解顺序...

    工程优化算法

    虽然它不是传统的优化算法,但其核心思想——不断减小搜索空间,与优化问题中的区间收缩策略相似。在C++中,二分法可以用于解决如查找、排序等问题,其效率高且易于实现。 在实际编程中,C++提供了强大的模板库和...

    ACM算法总结大全——超有用!.docx

    + 二分法求解单调函数相关知识 计算几何学 * 几何公式 * 叉积和点积的运用 * 多边型的简单算法(求面积)和相关判定(点在多边型内、多边型是否相交) * 凸包 中级算法 * C++的标准模版库的应用 * 较为复杂的...

    IOI国家集训队论文集1999-2019

    刘一鸣 -《一类搜索的优化思想——数据有序化》 陆可昱 -《长方体体积并》 饶向荣 -《病毒的DNA——剖析一道字符匹配问题解析过程》 邵烜程 -《数学思想助你一臂之力》 王知昆 -《浅谈用极大化思想解决最大子...

    (A070)炉温曲线的机理建模与优化设计.pdf

    对于问题二,建立了以最大过炉速度为目标的单目标优化模型,约束条件为满足问题一所建立的微分方程模型和工艺所要求的制程界限,并借助二分法进行求解得到最大传输速度为 76.2980 cm/min。 对于问题三,以衡量累计...

    强大的POJ分类——各类编程简单题及其算法分类

    【强大的POJ分类——各类编程简单题及其算法分类】 POJ,全称为Peking University Online Judge,是北京大学提供的一个在线编程题目平台,支持多种编程语言,包括Pascal、C、C++、Java、Fortran、Python等。这个...

    研究生课件——数值分析(东南大学)

    2. **插值与拟合**:学习如何通过有限的数据点构造函数近似,如拉格朗日插值、牛顿插值、样条插值等,以及最小二乘法进行数据拟合,这些在数据分析和模型建立时非常实用。 3. **数值微积分**:包括数值积分(如梯形...

    规划问题算法-6变循环发动机部件法建模及优化.pdf

    解决这类复杂非线性方程组,文章采用了改进的牛顿迭代法——阻尼牛顿法,这是一种迭代优化方法,通过引入阻尼因子来稳定迭代过程,防止发散。 **问题三:发动机性能参数的优化** 基于问题二的方程组,进一步推导...

    2018高教社杯全国大学生数建模竞赛A题评阅要点

    3. **计算方法**:推荐使用二分法来求解优化问题,该方法能够有效地处理具有单调性的优化问题。此外,也可以尝试其他优化算法,如梯度下降法或遗传算法等。 4. **模型验证**:通过在模型中引入随机误差来测试其稳健...

    区间分析及其在优化中的应用.doc

    本文主要探讨了区间分析的基本概念、原理以及其在行为生态学中的一个具体应用——觅食模型的优化。 #### 区间分析基础 **1.1 区间分析** **1.1.1 基本概念与符号** 区间分析是通过将数值用区间来表示的方法,来...

    非线性方程_非线性方程_matlab_非线性方程组_伞兵跳伞问题_工程数值计算_

    在本主题中,我们将探讨非线性方程的解决方法,特别是如何利用MATLAB进行数值求解,以及一个具体的实例——伞兵跳伞问题。 首先,非线性方程的基本形式可以表示为:f(x) = 0,其中f是一个不与x成线性关系的函数。...

    基于改进粒子群算法的阵列天线幅相容差设计.pdf

    因此,一种更为灵活且适应性强的优化工具——粒子群优化算法(PSO)被引入到这个问题中。 粒子群优化算法是一种启发式搜索算法,源于模拟鸟群觅食行为,能够有效地解决非线性和多峰优化问题。在本研究中,作者针对...

    二分查找,动态规划,视频讲解

    视频课程"09简约而不简单——二分法学习的四重境界"可能涵盖了二分查找的四种不同应用场景或深度理解,包括但不限于基础的二分查找、二分查找在区间操作中的应用、二分查找的变种以及在实际问题中的高级应用。...

Global site tag (gtag.js) - Google Analytics