树形结构问题的一种解决办法

在一个标准的树形结构里面,一般要想知道的操作基本上有查询子树和查询所有父树(路径),还有就是查询子树自身的深度问题,通过前些日子的总结发现一种结构可以很好的满足这些要求。
id parentID   name        path
———————————-
1     0              图书          0,1
2     1      
      管理类       0,1,2
3     2      
     名家作品     0,1,2,3
4     2      
     国内          0,1,2,4
5     2      
     外国          0,1,2,5
6     0      
     文学类       0,6
7     6      
     小说          0,6,7

上面这种结构就是我推荐的,这种结构对于我们通常用的id-parentID结构增加了一个路径(path)列,好处就是可以直接通过查询path列来找 出某个节点的子树和路径,比如2号节点的子树可以通过先查2号子树的path,然后再用like ‘0,1,2%’方式来得到。其路径可以通过in(0,1,2)查询到。深度可以通过explode(‘,’,$path),然后看看数组个数就可以看出 节点的深度了,这样就可以构建出一个树形结构了。
path列的构建可以在原有id-parentID结构上增加,通过id和parentid可以很方便的构建出某个节点的子树的path列(需要递归算法)。
常用的函数可以有三个:
nav($node) 根据节点求出其路径,先找出节点path然后根据path用"select * from category where id in ($path)",就能求出其路径所有节点了,方便导航。
tree($node)根据节点求出其所有子树,先找出节点path,然后用"select * from category where path like ‘$path%’",就可以找出所有子节点啦,这里可以通过计算每个节点的path中有几个元素explode(‘,’$path)计算每个节点的深度。
re_path($node)根据节点,重新构建子树的path,这个需要利用ID和ParentID两列,利用递归逐步计算,因为只有在改变子树隶属关系和建立新节点的时候用到,所以计算量应该不是很多。
好了上面是这种算法的基本构想,大家有什么新的构想,提出来讨论一下。

“改进前序遍历树”方法,这里有相关中文翻译介绍,http://www.nirvanastudio.org/category/database/
我这里提的方法很像“邻接列表模型”,就是增加了一个path列,所以针对邻接列表模型所遇到的最大的问题,子树、路径和深度问题得到了改善。
而改进前序遍历树方法也是有很大的局限的,就是当某个节点变换父节点时需要做大量的修改左右数值。而上面的方法修改量要小一点!
不知道这么说是否妥当,请指教!

附常用的三个函数:
function nav($id,$db){
$rs=$db->query("select * from category where id=’".$id."’");
$row=$rs->fetch();
$rs=$db->query("select * from category where id in (".$row[‘path’].") order by path");
return $rs->fetchall();
}
function tree($id,$db){
$rs=$db->query("select * from category where id=’".$id."’");
$row=$rs->fetch();
$rs=$db->query("select * from category where path like ‘".$row[‘path’]."%’ order by path");
$tree=$rs->fetchall();
foreach($tree as $key=>$row){
$depth=explode(‘,’,$row[‘path’]);
$depth=count($depth);
$tree[$key][‘depth’]=$depth;
}
return $tree;
}

function re_path($id,$parentpath=”,$db){//此函数使用前需要先获得父节点的path
       if($parentpath<>”){$path=$parentpath.’,’.$id;}else{$path=$id;}
$sql="update category set path=’".$path."’ where id=’"$id"’";
$rs=$db->query($sql);

$sql="select * from category where parentid=’".$id."’";
$rs=$db->query($sql);
while($row=$rs->fetch()){
   re_path($row[‘id’],$path,$db);
}
}

Read: 878

教你调均衡器

均衡器分段后的每个部分的作用:

1、20Hz–60Hz部分
这一段提升能给音乐强有力的感觉,给人很响的感觉,如雷声。是音乐中强劲有力的感觉。如果提升

过高,则又会混浊不清,造成清晰度不佳,特别是低频响应差和低频过重的音响设备。
2、60Hz–250Hz部分
这段是音乐的低频结构,它们包含了节奏部分的基础音,包括基音、节奏音的主音。它和高中音的比

例构成了音色结构的平衡特性。提升这一段可使声音丰满,过度提升会发出隆隆声。衰减这两段会使声音

单薄。
3、250Hz–2KHz部分
这段包含了大多数乐器的低频谐波,如果提升过多会使声音像电话里的声音。如把600Hz和1kHz过度

提升会使声音像喇叭的声音。如把3kHz提升过多会掩蔽说话的识别音,即口齿不清,并使唇音“mbv”难

以分辨。如把1kHz和3kHz过分提升会使声音具有金属感。由于人耳对这一频段比较敏感,通常不调节这一

段,过分提升这一段会使听觉疲劳。
4、2KHz–4kHz部分
这段频率属中频,如果提升得过高会掩盖说话的识别音,尤其是3kHz提升过高,会引起听觉疲劳。
5、4kHz–5KHz部分
这是具有临场感的频段,它影响语言和乐器等声音的清晰度。提升这一频段,使人感觉声源与听者的

距离显得稍近了一些;衰减5kHz,就会使声音的距离感变远;如果在5kHz左右提出升6dB,则会使整个混

合声音的声功率提升3dB。
6、6kHz–16kHz部分
这一频段控制着音色的明亮度,宏亮度和清晰度。一般来说提升这几段使声音宏亮,但不清晰,不可

能会引起齿音过重,衰减时声音变得清晰,但声音不宏亮。

Read: 759

patTemplate模板类的使用实例


前面讲了一个phplib的使用,作为模板驱动的代表patTemplate一样有着稳定,快速开发等等的优点,下面介绍一个简单实用的例子,我们使用test.php来解析模板test.html 并使用patTemplate作为模板引擎

test.html 模板文件:

<patTemplate:tmpl name="article">
<html>
<head>
<title>A patTemplate example</title>
</head>
<body>
<h3>{HEADLINE}</h3>
{CONTENT}
</body>
</html>
</patTemplate:tmpl>

其中的变量headlinecontent是需要我们通过patTemplate来解析过来的

test.php文件:

<?PHP
//包含进模板类文件
include("includes/patTemplate.php");  
// 初始化模板对象
$tmpl = new patTemplate();  
// 设定模板文件目录
$tmpl->setBasedir("templates");  
// 设定使用的模板文件
$tmpl->readTemplatesFromFile("example1.tmpl.html");  
// 向模板添加变量
$tmpl->addVar("article", "HEADLINE", "This is the headline");
$tmpl->addVar("article", "CONTENT", "And this is the content…");  
// 最终解析并显示模板
$tmpl->displayParsedTemplate("article");
?>  

这是最简单的一个例子,当然如果你熟悉PHPLIB的话,那么也可以轻松的在patTemplate里面使用象PHPLIB一样的循环结构,后面再介绍吧

Read: 147

JavaScript中类的定义[3]

5.较好的自定义类的方式

前面已经介绍了如何定义一个类,如何初始化一个类的实例,且类可以在function定义的函数体中添加成员,又可以用prototype定义类的成员,编程的代码显得混乱。

如何以一种清晰的方式来定义类呢?下面给出了一种类的实现模式。   

JavaScript中,由于对象灵活的性质,在构造函数中也可以为类添加成员,在增加灵活性的同时,也增加了代码的复杂度。

为了提高代码的可读性和开发效率,可以采用这种定义成员的方式,而使用prototype对象来替代,这样function的定义就是类的构造函数,符合传统意义类的实现:类名和构造函数名是相同的。

例如:

cls.prototype,不仅代码体积变大,而且易读性还不够。为了进一步改进,可以使用无类型对象的构造方法来指定prototype对象,从而实现类的成员定义:

function cls(){
 //构造函数
}
//成员定义
cls.prototype.someProperty=”sample”;
cls.prototype.someMethod=function(){  //方法实现代码 }  

虽然上面的代码对于类的定义已经清晰了很多,但每定义一个属性或方法,都需要使用一次

cls,构造函数直接用类名来实现,而成员使用无类型对象来定义,以列表的方式实现了所有属性和方法,并且可以在定义的同时初始化属性的值。这也更象传统意义面向对象语言中类的实现。只是构造函数和类的成员定义被分为了两个部分,这可看成JavaScript中定义类的一种固定模式,这样在使用时会更加容易理解。   

//定义一个类cls
function cls(){  //构造函数 }
//通过指定prototype对象来实现类的成员定义
class1.prototype={  someProperty:”sample”, someMethod:function(){   //方法代码  },  
…//其他属性和方法.
}   

上面的代码用一种很清晰的方式定义了

注意:在一个类的成员之间互相引用,必须通过this指针来进行,例如在上面例子中的someMethod方法中,如果要使用属性someProperty,必须通过this.someProperty的形式,因为在JavaScript中每个属性和方法都是独立的,它们通过this指针联系在一个对象上。

Read: 879

JavaScript中类的定义[2]

4.使用prototype原型对象定义类成员

使用prototype对象来定义类成员可以避免每实例化一个对象就创建一次类成员的缺点。 

new一个function时,prototype对象的成员将自动赋给所创建的对象。

Demo2

是一个JavaScript对象,可以为prototype对象添加、修改、删除方法和属性。从而为一个类添加成员定义。   

<script language=”JavaScript” type=”text/javascript”>
<!– //定义一个只有一个属性caption的类 
function cls(){  
this.caption=1;  
}  
//使用函数的prototype属性给类定义新成员 
cls.prototype.showcaption = function(){   alert(this.caption);  }  
//创建cls的一个实例 
var obj=new cls();
//调用通过prototype原型对象定义的showcaption方法 
obj.showcaption();
//–>
</script>   

prototype

了解了函数的prototype对象,现在再来看new的执行过程。   

1>创建一个新的对象,并让this指针指向它;   

2>将函数的prototype对象的所有成员都赋给这个新对象;   

3>执行函数体,对这个对象进行初始化操作;   

4>返回(1)中创建的对象。   

prototype对象的所有成员初始化过程发生在函数体(构造器)执行之前,所以可以在函数体内部调用prototype中定义的属性和方法。

Demo3

<script language=JavaScript type=text/javascript
!– //定义一个只有一个属性caption的类
function cls(){  this.caption=1;  this.showcaption(); }
//使用函数的prototype属性给类定义新成员
cls.prototype.showcaption=function(){  alert(this.caption); }
//创建cls的一个实例
var obj1=new cls(); //–>
/script>  

 

和上一段代码相比,这里在cls的内部调用了prototype中定义的方法showcaption,从而在对象的构造过程中就弹出了对话框,显示caption属性的值为1  

需要注意,原型对象的定义必须在创建类实例的语句之前,否则它将不会起作用。

Demo4

showcaption方法,就是因为该方法的定义是在实例化一个类的语句之后。   

<script language=”JavaScript” type=”text/javascript”>
<!– //定义一个只有一个属性caption的类
function cls(){  
this.caption=1;  
this.showcaption();
}
//创建cls的一个实例
var obj=new cls();
//在创建实例的语句之后使用函数的prototype属性给类定义新成员,只会对后面创建的对象有效
cls.prototype.showcaption=function(){  alert(this.caption); }
//–>
</script>   

这段代码将会产生运行时错误,显示对象没有

由此可见,prototype对象专用于设计类的成员,它是和一个类紧密相关的。

除此之外,prototype还有一个重要的属性:constructor,表示对该构造函数的引用,例如:

function cls(){  
alert(1);
}
cls.prototype.constructor(); //调用类的构造函数

  

这段代码运行后将会出现对话框,在上面显示文字“1”,从而可以看出一个prototype是和一个类的定义紧密相关的。

实际上:cls.prototype.constructor===cls  

Read: 776