[PHP技术]PHP二叉树的一些操作练习

操作方法

  • 01

    首先是创建一个树节点类,这个类有两个方法,compare()用于比较节点键值的大小,createNode()用于创建新节点。 [php] view plaincopyprint? // 树节点类 class binaryTreeNode { // 比较节点键值的大小 function compare($oldkey, $newkey){ return $newkey - $oldkey; } // 建立一个新节点 function createNode($key, $left, $right){ return array('k'=>$key, 'l'=>$left, 'r'=>$right); } } 然后再创建一个二叉树类。 [php] view plaincopyprint? // 二叉树类 class binaryTree { var $id = 1;            // 内部UID,自动加1 var $nodeCount = 0;     // 该树节点数,每插入一个加1 var $root = null;       // 树根的引用 var $tree = array();    // 树结构,中间存贮所有节点 var $_nodes = array();  // 存贮不同类型的节点,主要是为了引用该类的方法,便于继承,暂时没有用到 var $_node = null;      // 当前节点类的引用 // 构造函数,初始化 function binaryTree($nodetype = 'binaryTreeNode'){ if(!class_exists($nodetype)) $nodetype = 'binaryTreeNode'; $this->_nodes[$nodetype] = new $nodetype(); $this->_node =& $this->_nodes[$nodetype]; } // 设定节点类型,暂时用处不大,主要为扩展 function setNodeType($nodetype = 'binaryTreeNode'){ if(!class_exists($nodetype)) $nodetype = 'binaryTreeNode'; $this->_node =& $this->_nodes[$nodetype]; } // 插入一节点后修改所有相关节点的信息 // $pnode 为当前根节点,后两个参数为新节点的参数 // 即在树中插入一个新节点后,找到此节点所插入的位置并修改其父节点的信息 // 此函数本为递归,但因为是尾递归(rear-recursive),因此可以改成循环 function modifyTree(&$pnode, $key, $id){ $p =& $pnode; while(true){ $b = $this->_node->compare($p['k'], $key); if($b<=0) { if($p['l'] != 0) { $p =& $this->tree[$p['l']]; } else { $p['l'] = $id; break; } } else { if($p['r'] != 0) { $p =& $this->tree[$p['r']]; } else { $p['r'] = $id; break; } } } } // 重置树信息 function reset() { $this->tree = array(); $this->root = null; $this->id = 1; $this->nodeCount = 0; $this->_node = null; } // 插入一个键为$key的节点,并自动为此节点生成一个唯一ID function insertNode($key) { $node = $this->_node->createNode($key, 0, 0); $this->tree[$this->id] = $node; if($this->root == null) { $this->root =& $this->tree[1]; } else { $this->modifyTree($this->root, $key, $this->id); } $this->id ++; $this->nodeCount ++; } // 先根遍历,打印树结构,用的递归 // 此函数可修改用于任何用途 function preorder(&$root, $level, $r = 'r') { $p =& $root; if($r == 'l') $s = str_repeat("\t", 1); else $s = str_repeat("\t", $level); echo $s.$p['k'].""; if($p['r'] != 0) { $p1 =& $this->tree[$p['r']]; $this->preorder($p1, $level + 1, 'l'); } else { $s = str_repeat("\t", 1); echo $s.'null'."\n"; } if($p['l'] != 0) { $p1 =& $this->tree[$p['l']]; $this->preorder($p1, $level + 1); } else { $s = str_repeat("\t", $level + 1); echo $s.'null'."\n"; } } } 测试用代码: [php] view plaincopyprint? // 此函数主要是为了兼容性 function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000); } // 生成随机序列键值 function generateRandamSequence($min = 1, $max = 100){ srand(make_seed()); $n = $min; $a = array(); while($n <= $max) { $randval = rand($min, $max); if($a[$randval - $min] == '') { $a[$randval - $min] = $n; $n++; } } reset($a); ksort($a); reset($a); return $a; } $min = 1; $max = 100; // 将随机序列键值存入一数组内 $a = generateRandamSequence($min, $max); print_r($a);   // 打印数组 $tree = new binaryTree; // 建立一棵树 // 将节点按键值顺序插入到树中,同时调整树的结构 for($i=0;$i<$max-$min+1;$i++) $tree->insertNode($a[$i]); print_r($tree); // 打印树对象的内容 echo serialize($tree); // 打印树序列化之后的内容 echo "<hr>;\n<pre>;"; $t =& $tree->root; // 指定树根,为以下传入引用参数用 $tree->preorder($t, 0); // 先根遍历,打印树型结构 // 打印完毕可发现,键值比根键值小的所有节点均在根的左边,反之则在右边,每个节点都是如此 // 但此树不是平衡树(AVL树),因此查询效率还是比较低,特别是如果是连成一直线,则效率达到最低,不能利用树的对数特性了 echo "</pre>;"; // 打印完毕 完整版本: [php] view plaincopyprint? <?php // 树节点类 class binaryTreeNode { // 比较节点键值的大小 function compare($oldkey, $newkey){ return $newkey - $oldkey; } // 建立一个新节点 function createNode($key, $left, $right){ return array('k'=>$key, 'l'=>$left, 'r'=>$right); } } // 二叉树类 class binaryTree { var $id = 1;            // 内部UID,自动加1 var $nodeCount = 0;     // 该树节点数,每插入一个加1 var $root = null;       // 树根的引用 var $tree = array();    // 树结构,中间存贮所有节点 var $_nodes = array();  // 存贮不同类型的节点,主要是为了引用该类的方法,便于继承,暂时没有用到 var $_node = null;      // 当前节点类的引用 // 构造函数,初始化 function binaryTree($nodetype = 'binaryTreeNode'){ if(!class_exists($nodetype)) $nodetype = 'binaryTreeNode'; $this->_nodes[$nodetype] = new $nodetype(); $this->_node =& $this->_nodes[$nodetype]; } // 设定节点类型,暂时用处不大,主要为扩展 function setNodeType($nodetype = 'binaryTreeNode'){ if(!class_exists($nodetype)) $nodetype = 'binaryTreeNode'; $this->_node =& $this->_nodes[$nodetype]; } // 插入一节点后修改所有相关节点的信息 // $pnode 为当前根节点,后两个参数为新节点的参数 // 即在树中插入一个新节点后,找到此节点所插入的位置并修改其父节点的信息 // 此函数本为递归,但因为是尾递归(rear-recursive),因此可以改成循环 function modifyTree(&$pnode, $key, $id){ $p =& $pnode; while(true){ $b = $this->_node->compare($p['k'], $key); if($b<=0) { if($p['l'] != 0) { $p =& $this->tree[$p['l']]; } else { $p['l'] = $id; break; } } else { if($p['r'] != 0) { $p =& $this->tree[$p['r']]; } else { $p['r'] = $id; break; } } } } // 重置树信息 function reset() { $this->tree = array(); $this->root = null; $this->id = 1; $this->nodeCount = 0; $this->_node = null; } // 插入一个键为$key的节点,并自动为此节点生成一个唯一ID function insertNode($key) { $node = $this->_node->createNode($key, 0, 0); $this->tree[$this->id] = $node; if($this->root == null) { $this->root =& $this->tree[1]; } else { $this->modifyTree($this->root, $key, $this->id); } $this->id ++; $this->nodeCount ++; } // 先根遍历,打印树结构,用的递归 // 此函数可修改用于任何用途 function preorder(&$root, $level, $r = 'r') { $p =& $root; if($r == 'l') $s = str_repeat("\t", 1); else $s = str_repeat("\t", $level); echo $s.$p['k'].""; if($p['r'] != 0) { $p1 =& $this->tree[$p['r']]; $this->preorder($p1, $level + 1, 'l'); } else { $s = str_repeat("\t", 1); echo $s.'null'."\n"; } if($p['l'] != 0) { $p1 =& $this->tree[$p['l']]; $this->preorder($p1, $level + 1); } else { $s = str_repeat("\t", $level + 1); echo $s.'null'."\n"; } } } //--------------------------------------------------- // the following is the test // 此函数主要是为了兼容性 function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000); } // 生成随机序列键值 function generateRandamSequence($min = 1, $max = 100){ srand(make_seed()); $n = $min; $a = array(); while($n <= $max) { $randval = rand($min, $max); if($a[$randval - $min] == '') { $a[$randval - $min] = $n; $n++; } } reset($a); ksort($a); reset($a); return $a; } $min = 1; $max = 100; // 将随机序列键值存入一数组内 $a = generateRandamSequence($min, $max); print_r($a);   // 打印数组 $tree = new binaryTree; // 建立一棵树 // 将节点按键值顺序插入到树中,同时调整树的结构 for($i=0;$i<$max-$min+1;$i++) $tree->insertNode($a[$i]); print_r($tree); // 打印树对象的内容 echo serialize($tree); // 打印树序列化之后的内容 echo "<hr>;\n<pre>;"; $t =& $tree->root; // 指定树根,为以下传入引用参数用 $tree->preorder($t, 0); // 先根遍历,打印树型结构 // 打印完毕可发现,键值比根键值小的所有节点均在根的左边,反之则在右边,每个节点都是如此 // 但此树不是平衡树(AVL树),因此查询效率还是比较低,特别是如果是连成一直线,则效率达到最低,不能利用树的对数特性了 echo "</pre>;"; // 打印完毕 ?>

(0)

相关推荐

  • excel如何快速查询球星在某个赛季的单项技术数据?

    很多NBA球迷每个赛季都会用Excel表记录所喜爱球星多项技术的平均数据.但是,表一多起来,想查询相关球星在某个赛季的单项技术数据时,就显得费事了.那么,如何才能快速查询相关数据,而不需要在各个表中来 ...

  • 如何辨别硬盘是否返修过 翻新硬盘(返修盘)鉴定技巧

    现在市场上的返修盘还是挺多的,光从外表,包装,有点难分辨哦。 购物渠道很重要,不建议某宝购买,购买建议选择知名电商,或者店面,记得索取发票。 这样购买发现问题,售后容易解决!如果在店面购买,此方法可直 ...

  • 辨别自己买的是不是返修盘最简单的方法

    现在市场上的返修盘还是挺多的,光从外表,包装,有点难分辨哦。 购物渠道很重要,不建议某宝购买,购买建议选择知名电商,或者店面,记得索取发票。 这样购买发现问题,售后容易解决!如果在店面购买,此方法可直 ...

  • win10桌面路径怎么改?windows10桌面文件路径及临时文件夹路径修改方法详解

    win10桌面路径怎么改?小编将在下文演示win10桌面文件路径修改方法,很多朋友喜欢把一些文档放在电脑桌面上,这会占用C盘内存,那么该如何修改文件路径呢? 第一步、进入Win10这台电脑,然后进入系 ...

  • CPU之多媒体指令集详细介绍

    CPU依靠指令来计算和控制系统,每款CPU在设计时就规定了一系列与其硬件电路相配合的指令系统。指令的强弱也是CPU的重要指标,指令集是提高微处理器效率的最有效工具之一。从现阶段的主流体系结构讲,指令集 ...

  • 虾歌for Mac下载或者登陆出错的原因和解决方案

    很抱歉,近期虾歌for Mac出了些小问题,有部分童鞋反馈登陆链接不上,或者下载无进度,后期我们会尽快联系给您退换体验点的。非常抱歉哦~~~ 接下来是操作的方法跟贴图,请看 1.没有下载速度和不能添加 ...

  • 驴友走天下 QQ影像助力绚烂旅途

    天凉好个秋,十一黄金周即将来临,面对来之不易的七天长假,带着相机,背着本本,伙同朋友恋人,一同外出游玩成为大多数白领和大学生的不二之选。游玩必然拍照,尤其像这样的假期如不拍照留念实在对不住自己。无奈个 ...

  • 17寸最新游戏本华硕G750测评

    随着英特尔第四代酷睿处理器Haswell的上市,PC厂商也开始有条不紊地发布新产品或是更新旗下已有的型号。其中,在2013台北电脑展上,华硕展示了新款G750游戏本,一个明显的变化是取消了14及15英 ...

  • QQ受阻登不上怎么办?

    天天泡在网上的朋友们大多都离不开即时通讯软件,用QQ、MSN还有淘宝旺旺等工具和朋友们实时联系的确非常方便,一些公司为了避免员工无节制地使用这些即时通讯软件影响工作,会请网管加强管理,用技术方式阻断即 ...