|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
缺点:安全性不是太差了,还行,只要你充分利用系统自带的工具;唯一缺点就是执行效率慢,如何进行网站优化以后,效果会比较好。处理|算法|成绩 在网站建立中,分类算法的使用十分的广泛。在设计一个电子商铺时,要触及到商品分类;在设计宣布体系时,要触及到栏目或频道分类;在设计软件下载如许的法式时,要触及到软件的分类;如斯等等。可以说,分类是一个很广泛的成绩。
我经常面试一些法式员,并且我几近毫无破例地要问他们一些关于分类算法的成绩。上面的举几个我经常扣问的成绩。你以为你可以很轻松地回覆么^_^.
1、分类算法经常体现为树的暗示和遍历成绩。那末,请问:假如用数据库中的一个Table来表达树型分类,应当有几个字段?
2、若何疾速地从这个Table恢复出一棵树;
3、若何判别某个分类是不是是另外一个分类的子类;
4、若何查找某个分类的一切产物;
5、若何生成份类地点的途径。
6、若何新增分类;
在不限制分类的级数和每级分类的个数时,这些成绩并非可以轻松回覆的。本文试图处理这些成绩。
分类的数据布局
咱们晓得:分类的数据布局实践上是一棵树。在《数据布局》课程中,人人能够学过Tree的算法。因为在网站建立中咱们大批利用数据库,所以咱们将从Tree在数据库中的存储谈起。
为简化成绩,咱们假定每一个节点只需求保存Name这一个信息。咱们需求为每一个节点编号。编号的办法有良多种。在数据库中经常使用的就是主动编号。这在Access、SQLServer、Oracle中都是如许。假定编号字段为ID。为了暗示某个节点ID1是别的一个节点ID2的父节点,咱们需求在数据库中再保存一个字段,申明这个分类是属于哪一个节点的儿子。把这个字段取名为FatherID。如这里的ID2,其FatherID就是ID1。如许,咱们就失掉了分类Catalog的数据表界说:
CreateTable[Catalog](
[ID][int]NOTNULL,
[Name][nvarchar](50)NOTNULL,
[FatherID][int]NOTNULL
);
商定:咱们商定用-1作为最下面一层分类的父亲编码。编号为-1的分类。这是一个虚拟的分类。它在数据库中没有纪录。
若何恢复出一棵树
下面的Catalog界说的最大优势,就在于用它可以轻松地恢复出一棵树―分类树。为了更清晰地展现算法,咱们先思索一个复杂的成绩:如何显示某个分类的下一级分类。咱们晓得,要查询某个分类FID的下一级分类,SQL语句十分复杂:
selectNamefromcatalogwhereFatherID=FID
显示这些种别时,咱们复杂地用<LI>来做到:
<%
REMoConn---数据库毗连,挪用GetChildren时已翻开
REMFID-----以后分类的编号
FunctionGetChildren(oConn,FID)
strSQL="selectID,NamefromcatalogwhereFatherID="&FID
setrsCatalog=oConn.Execute(strSQL)
%>
<UL>
<%
DowhilenotrsCatalog.Eof
%>
<LI><%=rsCatalog("Name")%>
<%
Loop
%>
</UL>
<%
rsCatalog.Close
EndFunction
%>
如今咱们来看看若何显示FID下的一切分类。这需求用到递归算法。咱们只需求在GetChildren函数中复杂地对一切ID停止挪用:GetChildren(oConn,Catalog(“ID”))就能够了。
<%
REMoConn---数据库毗连,已翻开
REMFID-----以后分类的编号
FunctionGetChildren(oConn,FID)
strSQL="selectNamefromcatalogwhereFatherID="&FID
setrsCatalog=oConn.Execute(strSQL)
%>
<UL>
<%
DowhilenotrsCatalog.Eof
%>
<LI><%=rsCatalog("Name")%><%=GetChildren(oConn,Catalog("ID"))%>
<%
Loop
%>
</UL>
<%
rsCatalog.Close
EndFunction
%>
修正后的GetChildren就能够完成显示FID分类的一切子分类的义务。要显示一切的分类,只需求如斯挪用就能够了:
<%
REMstrConn--毗连数据库的字符串,请依据情形修正
setoConn=Server.CreateObject("ADODB.Connection")
oConn.OpenstrConn
GetChildren(oConn,-1)
oConn.Close
%>
若何查找某个分类的一切产物;
如今来处理咱们在后面提出的第四个成绩。第三个成绩留作习题。咱们假定产物的数据表以下界说:
CreateTableProduct(
[ID][int]NOTNULL,
[Name][nvchar]NOTNULL,
[FatherID][int]NOTNULL
);
个中,ID是产物的编号,Name是产物的称号,而FatherID是产物所属的分类。
对第四个成绩,很轻易想到的举措是:先找到这个分类FID的一切子类,然后查询一切子类下的一切产物。完成这个算法实践上很庞杂。代码大致以下:
<%
FunctionGetAllID(oConn,FID)
DimstrTemp
IfFID=-1then
strTemp=""
else
strTemp=","
endif
strSQL="selectNamefromcatalogwhereFatherID="&FID
setrsCatalog=oConn.Execute(strSQL)
DowhilenotrsCatalog.Eof
strTemp=strTemp&rsCatalog("ID")&GetAllID(oConn,Catalog("ID"))REM递归挪用
Loop
rsCatalog.Close
GetAllID=strTemp
EndFunction
REMstrConn--毗连数据库的字符串,请依据情形修正
setoConn=Server.CreateObject("ADODB.Connection")
oConn.OpenstrConn
FID=Request.QueryString("FID")
strSQL="selecttop100*fromProductwhereFatherIDin("&GetAllID(oConn,FID)&")"
setrsProduct=oConn.Execute(strSQL)
%>
<UL><%
DowhilenotrsProduct.EOF
%>
<LI><%=rsProduct("Name")%>
<%
Loop
%>
</UL>
<%rsProduct.Close
oConn.Close
%>
这个算法有良多弱点。试罗列几个以下:
1、因为咱们需求查询FID下的一切分类,当分类十分多时,算法将十分地不经济,并且,因为要机关一个很大的strSQL,试想假如有1000个分类,这个strSQL将很大,可否履行就是一个成绩。
2、咱们晓得,在SQL中利用In子句的效力长短常低的。这个算法不成防止地要利用In子句,效力很低。
我发明80%以上的法式员宠爱如许的算法,并在良多体系中大批地利用。仔细的法式员会发明他们写出了很慢的法式,但苦于找不到缘由。他们重复地反省SQL的履行效力,进步机械的层次,但效力的增添很少。
最基本的成绩就出在这个算法自己。算法定了,可以再优化的时机就不多了。咱们上面来引见一种算法,效力将是下面算法的10倍以上。优点:简单易学、开发速度快、有很多年“历史”,能找到非常多别人做好的程序来用、配合activeX功能强大,很多php做不到的asp+activeX能做到,例如银行安全控件 |
|