一种效率极高的分类算法(2)
来源:网络整理 责任编辑:栏目编辑 发表时间:2013-07-01 15:56 点击:次
REM strConn--连接数据库的字符串,请根据情况修改
set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open strConn
FID = Request.QueryString("FID")
strSQL = "select top 100 * from Product where FatherID in ("&GetAllID(oConn,FID)&")"
set rsProduct=oConn.Execute(strSQL)
%>
<UL><%
Do while not rsProduct.EOF
%>
<LI><%=rsProduct("Name")%>
<%
Loop
%>
</UL>
<%rsProduct.Close
oConn.Close
%>
这个算法有很多缺点。试列举几个如下:
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。(我是不是太罗嗦了J,但这一点很重要。再回头看看同学们前面提到的第五个问题。哈哈,这不就已经得到了分类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,
set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open strConn
FID = Request.QueryString("FID")
strSQL = "select top 100 * from Product where FatherID in ("&GetAllID(oConn,FID)&")"
set rsProduct=oConn.Execute(strSQL)
%>
<UL><%
Do while not rsProduct.EOF
%>
<LI><%=rsProduct("Name")%>
<%
Loop
%>
</UL>
<%rsProduct.Close
oConn.Close
%>
这个算法有很多缺点。试列举几个如下:
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。(我是不是太罗嗦了J,但这一点很重要。再回头看看同学们前面提到的第五个问题。哈哈,这不就已经得到了分类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,
相关新闻>>
最新推荐更多>>>
- 发表评论
-
- 最新评论 更多>>