您的位置:首页 > 编程语言 > PHP开发

PHP 将二叉查找树转换为双向链表,要求不能创建新节点,只能调节节点指针

2012-09-26 23:19 295 查看
<?php
#将二叉查找树转换为双向链表,要求不能创建新节点,只能调节节点指针

#解题思路是从树的底层开始,调整每个节点的左右子树,将左子树的最大节点与根节点相连,将又子树的最小节点与根节点相连
#我们把节点的left当做链表的pre指针,right当做链表的next指针
#直到所有子树以及根节点转换完成

#树节点
class Node {
public $data = null;
public $parent = null;
public $left = null;
public $right = null;
}

#查找树最小节点
function search_min($root) {
$cnode = $root;
while ($cnode->left != null) {
$cnode = $cnode->left;
}

return $cnode;
}

#查找树的最打节点
function search_max($root) {
$cnode = $root;
while ($cnode->right != null) {
$cnode = $cnode->right;
}

return $cnode;
}

#查找某个节点中序遍历的前趋
function predecessor($node) {
#如果该节点存在左子树,则查找其左子树的最大值
if ($node->left != null) {
return search_max($left);
}

#否则查找其父节点,直到当前节点是其父节点的右孩子
$p = $node->parent;
while ($p != null && $node == $p->left) {
$node = $p;
$p = $p->parent;
}

return $p;
}

#查找某个节点中序遍历的后继
function successor($node) {
#如果该节点存在右子树,则查找其右子树的最小值
if ($node->right != null) {
return search_min($node->right);
}

#否则查找其父节点,直到当前节点是其父节点的左孩子
$p = $node->parent;
while ($p != null && $node == $p->right) {
$node = $p;
$p = $p->parent;
}

return $p;
}

#插入节点
function insert_node($root, $node) {
$cnode = $root;
$p = $root;
#查找合适的插入位置
while ($cnode != null) {
$p = $cnode;
if ($cnode->data > $node->data) {
$cnode = $cnode->left;
} else {
$cnode = $cnode->right;
}
}

if ($p == null) { #如果p为null,说明是空树
$root = $node;
} else {
if ($p->data > $node->data) {
$p->left = $node;
} else {
$p->right = $node;
}
$node->parent = $p;
}

return $root;
}

#删除结点
function delete_node($root, $dnode) {
if ($dnode->left != null || $dnode->right != null) {
$c = $dnode;
} else {
$c = successor($dnode);
}

if ($c->left != null) {
$s = $c->left;
} else {
$s = $c->right;
}

if ($s != null) {
$s->parent = $c->parent;
}

if ($c->parent == null) { #c是根节点
$root = $s;
} else if ($c == $c->parent->left) {
$c->parent->left = $s;
} else {
$c->parent->right = $s;
}

if ($dnode != $c) {
$dnode->data = $c->data;
}

return $root;
}

#使用数组建立二叉查找树
function build_btree($a) {
$root = new Node();
$root->data= $a[0];

for ($i = 1; $i < count($a); $i++) {
$node = new Node();
$node->data = $a[$i];
insert_node($root, $node);
}

return $root;
}

#二叉树中序遍历
function inorder_traverse($root) {
if ($root->left != null) {
inorder_traverse($root->left);
}

echo $root->data . " ";

if ($root->right != null) {
inorder_traverse($root->right);
}
}

#链表的遍历
function linked_list_traverse($head) {
$node = $head;
while ($node != null) {
echo $node->data . " ";
$node = $node->right;
}
}

#二叉查找树变双向链表
function change($root) {
#如果有子节点,就往子节点递归,直到最后一个非叶子节点,将他们的左右子节点连接成链表
#然后逐层往上递归
if ($root->left != null) {
btree_to_doublelist($root->left);
#这里不用担心调整左右节点以后search_max查找出来的节点会出错,因为虽然调整以后树的结构变了,但是他依然保有二叉树的性质
#看图1就知道了
$predecessor = search_max($root->left);
$predecessor->right = $root;
$root->left = $predecessor;
}

if ($root->right != null) {
btree_to_doublelist($root->right);
$successor = search_min($root->right);
$successor->left = $root;
$root->right = $successor;
}
}

function btree_to_doublelist($root) {
#链表头节点就是二叉查找树的最小节点
$head = search_min($root);
change($root);
return $head;
}

$a = array(10, 6, 14, 4, 8, 12, 16);
$root = build_btree($a);
inorder_traverse($root);
echo "<br>";
$link_head = btree_to_doublelist($root);
linked_list_traverse($link_head);
echo "<br>";
?>



4 6 8 10 12 14 16
4 6 8 10 12 14 16





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐