整理一个asp多级树型分类问题的解决方法(5)

来源:csdn 时间:2007-10-17 18:38:00 

这个算法有很多缺点。试列举几个如下:

1、由于我们需要查询FID下的所有分类,当分类非常多时,算法将非常地不经济,而且,由于要构造一个很大的strSQL,试想如果有1000个分类,这个strSQL将很大,能否执行就是一个问题。

2、我们知道,在SQL中使用In子句的效率是非常低的。这个算法不可避免地要使用In子句,效率很低。

我发现80%以上的程序员钟爱这样的算法,并在很多系统中大量地使用。细心的程序员会发现他们写出了很慢的程序,但苦于找不到原因。他们反复地检查SQL的执行效率,提高机器的档次,但效率的增加很少。

最根本的问题就出在这个算法本身。算法定了,能够再优化的机会就不多了。我们下面来介绍一种算法,效率将是上面算法的10倍以上。 

分类编码算法

问题就出在前面我们采用了顺序编码,这是一种最简单的编码方法。大家知道,简单并不意味着效率。实际上,编码科学是程序员必修的课程。下面,我们通过设计一种编码算法,使分类的编号ID中同时包含了其父类的信息。一个五级分类的例子如下:
 
此例中,用32(4+7+7+7+7)位整数来编码,其中,第一级分类有4位,可以表达16种分类。第二级到第五级分类分别有7位,可以表达128个子分类。
显然,如果我们得到一个编码为  1092787200  的分类,我们就知道:由于其编码为
 0100  0001001  0001010  0111000  0000000
所 以它是第四级分类。其父类的二进制编码是0100  0001001  0001010  0000000  0000000,十进制编号为1092780032。依次我们还可以知道,其父类的父类编码是0100  0001001  0000000  0000000  0000000,其父类的父类的父类编码是0100  0000000  0000000  0000000  0000000。(我是不是太罗嗦了:,但这一点很重要。再回头看看我们前面提到的第五个问题。哈哈,这不就已经得到了分类1092787200所在的 分类路径了吗?)。
现在我们在一般的情况下来讨论类别编码问题。设类别的层次为k,第i层的编码位数为Ni,  那么总的编码位数为N(N1+N2+..+Nk)。我们就得到任何一个类别的编码形式如下:
2^(N-(N1+N2+…+Ni))*j  +  父类编码
其中,i表示第i层,j表示当前层的第j个分类。

这样我们就把任何分类的编码分成了两个部分,其中一部分是它的层编码,一部分是它的父类编码。由下面公式定一的k个编码我们称为特征码:(因为i可以取k个值,所以有k个)
2^N-2^(N-(N1+N2+…+Ni))

对于任何给定的类别ID,如果我们把ID和k个特征码"相与",得到的非0编码,就是其所有父类的编码!

位编码算法

对任何顺序编码的Catalog表,我们可以设计一个位编码算法,将所有的类别编码规格化为位编码。在具体实现时,我们先创建一个临时表:


Create  TempCatalog(
 [OldID]  [int]  NOT  NULL,
 [NewID]  [int]  NOT  NULL,
 [OldFatherID]  [int]  NOT  NULL,
 [NewFatherID]  [int]  NOT  NULL
);


在这个表中,我们保留所有原来的类别编号OldID和其父类编号OldFatherID,以及重新计算的满足位编码要求的相应编号NewID、NewFatherID。
程序如下:



<% 
REM  oConn---数据库连接,已经打开 
REM  OldFather---原来的父类编号 
REM  NewFather---新的父类编号 
REM  N---编码总位数 
REM  Ni--每一级的编码位数数组 
REM  Level--当前的级数 
  
sub  FormatAllID(oConn,OldFather,NewFather,N,Nm,Ni  byref,Level) 
 strSQL  =  "select  CatalogID  ,  FatherID  from  Catalog  where  FatherID="  &  OldFather 
 set  rsCatalog=oConn.Execute(  strSQL  ) 
  
 j  =  1 
 do  while  not  rsCatalog.EOF 
   i  =  2  ^(N  -  Nm)  *  j 
   if  Level  then  i=  i  +  NewFather 
    
        
   OldCatalog  =  rsCatalog("CatalogID") 
   NewCatalog  =  i 
    
   REM  写入临时表 
   strSQL  =  "Insert  into  TempCatalog  (OldCatalogID  ,  NewCatalogID  ,  OldFatherID  ,  NewFatherID)" 
   strSQL  =  strSQL  &  "  values("  &  OldCatalog  &  "  ,  "  &  NewCatalog  &  "  ,  "  &  OldFather  &  "  ,  "  &  NewFather  &  ")" 
  
   Conn.Execute  strSQL 
    
   REM  递归调用FormatAllID 
   Nm  =  Nm  +  Ni(Level+1)     
   FormatAllID  oConn,OldCatalog  ,  NewCatalog  ,N,Nm,Ni,Level  +  1 
    
   rsCatalog.MoveNext 
    
   j  =  j+1 
 loop 
    
 rsCatalog.Close 
end  sub 
%>



调用这个算法的一个例子如下:



<% 
REM  定义编码参数,其中N为总位数,Ni为每一级的位数。 
 Dim  N,Ni(5) 
  
 Ni(1)  =  4 
  
 N  =  Ni(1) 
  
 for  i=2  to  5 
   Ni(i)  =  7 
   N  =  N  +  Ni(i) 
 next 
  
REM  打开数据库,创建临时表   
 strSQL  =  "Create  TempCatalog(  [OldID]  [int]  NOT  NULL,  [NewID]  [int]  NOT  NULL,  [OldFatherID]  [int]  NOT  NULL,  [NewFatherID]  [int]  NOT  NULL);" 
       Set  Conn  =  Server.CreateObject("ADODB.Connection")   
       Conn.Open  Application("strConn") 
       Conn.Execute  strSQL 
            
REM  调用规格化例程 
 FormatAllID  Conn,-1,-1,N,Ni(1),Ni,0 
  
REM  ------------------------------------------------------------------------ 
REM  在此处更新所有相关表的类别编码为新的编码即可。 
REM  ------------------------------------------------------------------------ 
  
REM  关闭数据库 
 strSQL=  "drop  table  TempCatalog;" 
 Conn.Execute  strSQL 
 Conn.Close 
%> 


 

标签:树,分类,asp
0
投稿

猜你喜欢

  • 再谈动态添加样式规则

    2009-09-02 13:10:00
  • ASP连接11种数据库语法总结

    2007-09-29 12:07:00
  • sqlserver自动增长列引起的问题解决方法

    2011-10-24 19:37:28
  • Firefox 3.5 新增加的支持(整理)

    2009-08-01 12:51:00
  • 网页上的广告条设计思考

    2008-06-29 14:16:00
  • ie6 img onload

    2009-04-08 17:23:00
  • 嵌入式Web视频点播系统实现方法

    2007-10-10 21:17:00
  • 13家著名科技公司logo标识来历及演变

    2008-02-19 16:42:00
  • 网页版面布局的方法及技巧

    2007-10-29 12:41:00
  • asp如何处理页面执行时发生的错误?

    2009-11-14 20:43:00
  • JavaScript奇怪的比较——隐式类型转换

    2009-02-15 13:06:00
  • 如何判断发言是否为空?

    2010-01-12 20:15:00
  • asp如何用下拉列表显示数据库里的内容?

    2010-06-16 09:54:00
  • SQL Server中通过reverse取某个最后一次出现的符号后面的内容(字符串反转)

    2012-07-11 15:59:36
  • 做网站要习惯化与去习惯化

    2008-06-18 13:36:00
  • JavaScript版无组件上传类

    2007-10-06 23:16:00
  • SQL Server数据库超级管理员账号防护

    2008-12-22 16:30:00
  • 谷歌历年母亲节Logo一览

    2009-05-11 12:17:00
  • CSS写法性能

    2009-05-28 19:09:00
  • 变态输入框——再谈校验包容性(一)

    2009-10-10 13:23:00
  • asp之家 网络编程 m.aspxhome.com