博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP 二叉查找树
阅读量:4698 次
发布时间:2019-06-09

本文共 5489 字,大约阅读时间需要 18 分钟。

二叉查找树:简单点说就是颗做孩子小,右孩子大的树

说几个关键点

 

最小值:总是树的最左节点的key

 

最大值:总是树的最右节点的key

 

前趋:按照中序遍历的顺序,遍历输出时当前节点的前一个节点

        如果当前节点有左子节点,前驱就是当前节点的左边的最右节点,也可以认为是以当前节点的左孩子为根的树的最大值

        如果当前节点没有左子节点,前驱就是找到一个父节点,使得当前节点位于该父节点的右边,不明白的看代码

 

后继:按照中序遍历的顺序,遍历输出时当前节点的后一个节点

        如果当前节点有右子节点,后继就是当前节点的右边的最左节点,也可以认为是以当前节点的右孩子为根的树的最小值

        如果当前节点没有柚子节点,后继就是找到一个父节点,使得当前节点位于该父节点的左边

 

插入节点:插入节点的思想是从root开始用当前节点的key值比较待插入节点的key值,待插入key比当前节点key小,则当前节点变为当前节点左孩子,否则变为当前节点右孩子,继续比较key,直到当前节点为null(到达树底部),记下比较完的最后一个叶子节点为P,如果P不为空,比较这个叶子节点和待插入节点的key,待插入节点小则作为这个叶子节点的左孩子,否则作为他的右孩子,如果P为空,说明这是一个空树,直接将待插入节点作为根返回即可

 

删除节点:删除节点分三种情况

1)如果待删除节点没有孩子,直接将节点删除即可。

2)如果待删除节点只有一个孩子,将待删除节点删除,并连接待删除节点的孩子和父亲,原来的左孩子还是作为其父节点的左孩子,原来的右孩子还是作为其父亲的右孩子

3)如果待删除节点有两个孩子,则找到待删除节点的直接后继,将后继删除(直接后继肯定只有一个子节点,要不然不可能是一个直接后继),然后按照2)连接后继的子节点和父节点,最后交换待删除节点和后继节点的key值

 

下面是代码和输出结果

1 
key == $K) { 16 return $cnode; 17 } else if ($cnode->key > $k) { 18 $cnode = $cnode->left; 19 } else { 20 $cnode = $cnode->right; 21 } 22 } 23 24 return $cnode; 25 } 26 27 #查找最小关键字 28 function search_minimum($root) { 29 $cnode = $root; 30 while ($cnode->left != null) { 31 $cnode = $cnode->left; 32 } 33 return $cnode; 34 } 35 36 #查找最大关键字 37 function search_maximum($root) { 38 $cnode = $root; 39 while ($cnode->right != null) { 40 $cnode = $cnode->right; 41 } 42 return $cnode; 43 } 44 45 #查找中序遍历前驱节点 46 function predecessor($x) { 47 if ($x->left !== null) { #左子结点存在,直接返回左子结点的最右子节点 48 return search_maximum($x->left); 49 } 50 #否则查找其父节点,直到当前节点位于父节点的右边 51 $p = $x->parent; 52 while ($p !== null && $x == $p->left) { #如果x是p的左孩子,说明p是x的后继,我们需要找的是p是x的前驱 53 $x = $p; 54 $p = $p->parent; 55 } 56 return $p; 57 } 58 59 #查找中序遍历的后继结点 60 function successor($x) { 61 if ($x->right !== null) { 62 return search_minimum($x->right); 63 } 64 $p = $x->parent; 65 while ($p !== null && $x = $p->right) { 66 $x = $p; 67 $p = $p->parent; 68 } 69 70 return $p; 71 } 72 73 #插入结点 74 function insert($root, $inode) { 75 $cnode = $root; 76 $pnode = null; 77 while ($cnode !== null) { #为inode找到合适的插入位置 78 $pnode = $cnode; 79 if ($cnode->key > $inode->key) { 80 $cnode = $cnode->left; 81 } else { 82 $cnode = $cnode->right; 83 } 84 } 85 86 $inode->parent = $pnode; 87 if ($pnode === null) { #pnode == null,说明是空树 88 $root = $inode; 89 } else { 90 if ($pnode->key > $inode->key) { 91 $pnode->left = $inode; 92 } else { 93 $pnode->right = $inode; 94 } 95 } 96 // print_r($root); 97 // echo "
"; 98 } 99 100 #删除结点101 function delete($root, $dnode) {102 if ($dnode-> left === null || $dnode->right === null) { #如果待删除结点无子节点或只有一个子节点,则c = dnode103 $c = $dnode;104 } else { #如果待删除结点有两个子节点,c置为dnode的直接后继,以待最后将待删除结点的值换为其后继的值105 $c = successor($dnode);106 }107 108 if ($c->left !== null) {109 $s = $c->left;110 } else {111 $s = $c->right;112 }113 114 if ($s !== null) { #将c的子节点的父母结点置为c的父母结点,此处c只可能有1个子节点,因为如果c有两个子节点,则c不可能是dnode的直接后继115 $s->parent = $c->parent;116 }117 118 if ($c->parent === null) { #如果c的父母为空,说明c=dnode是根节点,删除根节点后直接将根节点置为根节点的子节点,此处dnode是根节点,且拥有两个子节点,则c是dnode的后继结点,c的父母就不会为空,就不会进入这个if119 $root = $s;120 } else if ($c == $c->parent->left) { #如果c是其父节点的左右子节点,则将c父母的左右子节点置为c的左右子节点121 $c->parent->left = $s;122 } else {123 $c->parent->right = $s;124 }125 126 #如果c!=dnode,说明c是dnode的后继结点,交换c和dnode的key值127 if ($c != $dnode) {128 $dnode->key = $c->key;129 }130 131 #返回根节点132 return $root;133 }134 135 #使用数组构造二叉查找树136 function build_iterative_tree($arr) {137 $root = new Node();138 $root->key = $arr[0];139 for ($i = 1; $i < count($arr); $i++) {140 $new_node = new Node();141 $new_node->key = $arr[$i];142 insert($root, $new_node);143 }144 return $root;145 }146 147 #二叉查找树中序遍历148 function inorder_traverse($root) {149 if ($root->left !== null) {150 inorder_traverse($root->left);151 }152 153 echo $root->key . " ";154 155 if ($root->right !== null) {156 inorder_traverse($root->right);157 }158 }159 160 $arr = array(55, 1, 5, 9, 3, 4, 2, 2, 7, 8, 8, 0, 1);161 $root = build_iterative_tree($arr);162 inorder_traverse($root);163 echo "
";164 echo search_maximum($root)->key;165 echo "
";166 echo search_minimum($root)->key;167 echo "
";168 $inode = new Node();169 $inode->key = 99;170 insert($root, $inode);171 inorder_traverse($root);172 echo "
";173 delete($root, $root);174 inorder_traverse($root);175 echo "
";176 ?>

0 1 1 2 2 3 4 5 7 8 8 9 55 

55

0
0 1 1 2 2 3 4 5 7 8 8 9 55 99 
0 1 1 2 2 3 4 5 7 8 8 9 99 

转载于:https://www.cnblogs.com/zemliu/archive/2012/09/19/2692405.html

你可能感兴趣的文章