tree
1 二叉查找树 2 <?php 3 4 /** 5 * 节点类 6 */ 7 class Node 8 { 9 public $val; 10 public $left; 11 public $right; 12 13 public function __construct( $val ) 14 { 15 $this->val = $val; 16 } 17 } 18 19 /** 20 * 二叉搜索树; 21 */ 22 class SearchTree 23 { 24 private $_root; //根节点 25 26 public function __construct() 27 { 28 $this->_root = null; 29 } 30 31 public function insert( $val ) 32 { 33 $this->_root = $this->_insert( $val, $this->_root ); 34 return $this->_root; 35 } 36 37 private function _insert( $val, $tree ) 38 { 39 if( $tree == null ) { 40 $node = new Node( $val ); 41 return $node; 42 } 43 44 if( $val > $tree->val ) { 45 $tree->right = $this->_insert( $val, $tree->right ); 46 }else if( $val < $tree->val ) { 47 $tree->left = $this->_insert( $val, $tree->left ); 48 }else { 49 // do nothing. 50 } 51 return $tree; 52 } 53 54 public function find( $x ) 55 { 56 return $this->_find( $x, $this->_root ); 57 } 58 59 private function _find( $x, $tree ) 60 { 61 if( $tree == null ) 62 return null; 63 64 if( $tree->val == $x ) 65 return $tree; 66 else if( $tree->val > $x ) { 67 return $this->_find( $x, $tree->left ); 68 }else { 69 return $this->_find( $x, $tree->right ); 70 } 71 } 72 73 public function findMax() 74 { 75 $tmp = $this->_root; 76 while( $tmp && $tmp->right ) { 77 $tmp = $tmp->right; 78 } 79 80 return $tmp; 81 } 82 83 public function findMin( $tree = null ) 84 { 85 $tmp = $tree ? $tree : $this->_root; 86 while( $tmp && $tmp->left ) { 87 $tmp = $tmp->left; 88 } 89 90 return $tmp; 91 } 92 93 public function delete( $x ) 94 { 95 $this->_root = $this->_delete( $x, $this->_root ); 96 return $this->_root; 97 } 98 99 public function _delete( $x, $tree ) 100 { 101 if( $tree == null ) 102 return $tree; 103 104 if( $x > $tree->val ) { 105 $tree->right = $this->_delete( $x, $tree->right ); 106 }else if( $x < $tree->val ) { 107 $tree->left = $this->_delete( $x, $tree->left ); 108 }else { 109 //删除节点。 110 if( $tree->left == null && $tree->right == null ) { 111 //叶子节点,直接删除 112 $tree = null; 113 return $tree; 114 } 115 116 if( $tree->left == null ) { 117 $tree = $tree->right; 118 }else if( $tree->right == null ) { 119 $tree = $tree->left; 120 }else { 121 //左右都有子节点。右边找最小子节点 代替当前节点 122 $rightMin = $this->findMin( $tree->right ); 123 $tree->right = $this->_delete( $rightMin->val, $tree->right ); 124 $rightMin->left = $tree->left; 125 $rightMin->right = $tree->right; 126 $tree = $rightMin; 127 unset( $rightMin ); 128 } 129 } 130 return $tree; 131 } 132 133 /** 134 * 中序输出 135 */ 136 public function inEcho() 137 { 138 $this->_inEcho( $this->_root ); 139 echo '~~~~~~~~~~ ' . PHP_EOL; 140 } 141 142 private function _inEcho( $tree ) 143 { 144 if( $tree == null ) { 145 return; 146 } 147 148 $this->_inEcho( $tree->left ); 149 echo $tree->val . PHP_EOL; 150 $this->_inEcho( $tree->right ); 151 } 152 153 public function dump() 154 { 155 $ret = []; 156 if( $this->_root == null ) 157 return $ret; 158 159 $stack = new SplStack(); 160 $stack->push( [$this->_root] ); 161 while( !$stack->isEmpty() ) { 162 $node = $stack->pop(); 163 164 $temp = $stackVal = []; 165 $isAllNull = true; 166 foreach( $node as $_node ) { 167 if( $_node == null ) 168 $temp[] = ''; 169 else { 170 $temp[] = $_node->val; 171 $isAllNull = false; 172 } 173 174 if( $_node && $_node->left ) { 175 $stackVal[] = $_node->left; 176 }else { 177 $stackVal[] = null; 178 } 179 if( $_node && $_node->right ) { 180 $stackVal[] = $_node->right; 181 }else { 182 $stackVal[] = null; 183 } 184 } 185 if( !$isAllNull ) { 186 if( $stackVal ) $stack->push( $stackVal ); 187 if( $temp ) $ret[] = $temp; 188 } 189 } 190 191 $retCount = count( $ret ) - 1; 192 foreach( $ret as $_retVal ) { 193 echo str_repeat( ' ', $retCount ); 194 $_retValCount = count( $_retVal ); 195 $_tempEcho = ''; 196 for( $i = 0; $i < $_retValCount; $i+= 2 ) { 197 $_tempEcho .= '|'; 198 if( isset( $_retVal[$i+1] ) ){ 199 $_tempEcho .= $_retVal[$i] . '-' . $_retVal[$i+1]; 200 }else 201 $_tempEcho .= $_retVal[$i]; 202 $_tempEcho .= '|'; 203 } 204 echo str_replace( '||', '|', $_tempEcho ); 205 $retCount--; 206 echo PHP_EOL; 207 } 208 } 209 210 } 211 212 213 $tree = new SearchTree(); 214 $tree->insert( 100 ); 215 $tree->insert( 20 ); 216 $tree->insert( 30 ); 217 $tree->insert( 15 ); 218 $tree->insert( 5 ); 219 $tree->insert( 90 ); 220 $tree->insert( 17 ); 221 $tree->insert( 18 ); 222 $tree->insert( 188 ); 223 $tree->dump(); 224 // $tree->delete( 100 ); 225 // $tree->dump(); 226 // var_dump( $tree->find( 150 ) ); 227 var_dump( $tree->findMax() );
1 avl树 2 <?php 3 class Node 4 { 5 public $val; 6 public $left; 7 public $right; 8 public $height; 9 10 public function __construct( $val ) 11 { 12 $this->val = $val; 13 $this->height = 0; 14 } 15 } 16 17 18 class AvlTree 19 { 20 private $_root; 21 22 public function __construct() 23 { 24 $this->_root = null; 25 } 26 27 public function find( $x ) 28 { 29 return $this->_find( $x, $this->_root ); 30 } 31 32 private function _find( $x, $tree ) 33 { 34 if( $tree == null ) 35 return null; 36 37 if( $tree->val == $x ) 38 return $tree; 39 else if( $tree->val > $x ) { 40 return $this->_find( $x, $tree->left ); 41 }else { 42 return $this->_find( $x, $tree->right ); 43 } 44 } 45 46 public function findMax() 47 { 48 $tmp = $this->_root; 49 while( $tmp && $tmp->right ) { 50 $tmp = $tmp->right; 51 } 52 53 return $tmp; 54 } 55 56 public function findMin( $tree = null ) 57 { 58 $tmp = $tree ? $tree : $this->_root; 59 while( $tmp && $tmp->left ) { 60 $tmp = $tmp->left; 61 } 62 63 return $tmp; 64 } 65 66 public function getHeight( $tree ) { 67 if( $tree == null ) 68 return -1; 69 else 70 return $tree->height; 71 } 72 73 public function insert( $x ) 74 { 75 $this->_root = $this->_insert( $x, $this->_root ); 76 return $this->_root; 77 } 78 79 private function _insert( $val, $tree ) 80 { 81 if( $tree == null ) { 82 $node = new Node( $val ); 83 return $node; 84 } 85 86 if( $val > $tree->val ) { 87 $tree->right = $this->_insert( $val, $tree->right ); 88 if( $this->getHeight( $tree->right ) - $this->getHeight( $tree->left ) == 2 ) { 89 if( $val > $tree->right->val ) { 90 // var_dump( "val = {$val} ;; rotate = singleRotateWithRight "); 91 $tree = $this->singleRotateWithRight( $tree ); 92 }else { 93 // var_dump( "val = {$val} ;; rotate = doubleRotateWithRight "); 94 $tree = $this->doubleRotateWithRight( $tree ); 95 } 96 } 97 }else if( $val < $tree->val ) { 98 $tree->left = $this->_insert( $val, $tree->left ); 99 if( $this->getHeight( $tree->left ) - $this->getHeight( $tree->right ) == 2 ) { 100 if( $val < $tree->left->val ) { 101 // var_dump( "val = {$val} ;; rotate = singleRotateWithLeft "); 102 103 $tree = $this->singleRotateWithLeft( $tree ); 104 }else { 105 // var_dump( "val = {$val} ;; rotate = doubleRotateWithLeft "); 106 107 $tree = $this->doubleRotateWithLeft( $tree ); 108 } 109 } 110 }else { 111 // do nothing. 112 } 113 114 $tree->height = max( $this->getHeight( $tree->left ), $this->getHeight( $tree->right ) ) + 1; 115 116 return $tree; 117 } 118 119 private function singleRotateWithRight( $tree ) 120 { 121 $newRoot = $tree->right; 122 $tree->right = $newRoot->left; 123 $newRoot->left = $tree; 124 125 $newRoot->height = max( $this->getHeight( $newRoot->left ), $this->getHeight( $newRoot->right ) ) + 1; 126 $tree->height = max( $this->getHeight( $tree->left ), $this->getHeight( $tree->right ) ) + 1; 127 128 return $newRoot; 129 } 130 131 private function singleRotateWithLeft( $tree ) 132 { 133 $newRoot = $tree->left; 134 $tree->left = $newRoot->right; 135 $newRoot->right = $tree; 136 137 $newRoot->height = max( $this->getHeight( $newRoot->left ), $this->getHeight( $newRoot->right ) ) + 1; 138 $tree->height = max( $this->getHeight( $tree->left ), $this->getHeight( $tree->right ) ) + 1; 139 140 return $newRoot; 141 } 142 143 private function doubleRotateWithRight( $tree ) 144 { 145 $tree->right = $this->singleRotateWithLeft( $tree->right ); 146 return $this->singleRotateWithRight( $tree ); 147 } 148 149 private function doubleRotateWithLeft( $tree ) 150 { 151 $tree->left = $this->singleRotateWithRight( $tree->left ); 152 return $this->singleRotateWithLeft( $tree ); 153 } 154 155 public function dump() 156 { 157 $ret = []; 158 if( $this->_root == null ) 159 return $ret; 160 161 $stack = new SplStack(); 162 $stack->push( [$this->_root] ); 163 while( !$stack->isEmpty() ) { 164 $node = $stack->pop(); 165 166 $temp = $stackVal = []; 167 $isAllNull = true; 168 foreach( $node as $_node ) { 169 if( $_node == null ) 170 $temp[] = ''; 171 else { 172 $temp[] = $_node->val; 173 $isAllNull = false; 174 } 175 176 if( $_node && $_node->left ) { 177 $stackVal[] = $_node->left; 178 }else { 179 $stackVal[] = null; 180 } 181 if( $_node && $_node->right ) { 182 $stackVal[] = $_node->right; 183 }else { 184 $stackVal[] = null; 185 } 186 } 187 if( !$isAllNull ) { 188 if( $stackVal ) $stack->push( $stackVal ); 189 if( $temp ) $ret[] = $temp; 190 } 191 } 192 193 $retCount = count( $ret ) - 1; 194 foreach( $ret as $_retVal ) { 195 echo str_repeat( ' ', $retCount ); 196 $_retValCount = count( $_retVal ); 197 $_tempEcho = ''; 198 for( $i = 0; $i < $_retValCount; $i+= 2 ) { 199 $_tempEcho .= '|'; 200 if( isset( $_retVal[$i+1] ) ){ 201 $_tempEcho .= $_retVal[$i] . '-' . $_retVal[$i+1]; 202 }else 203 $_tempEcho .= $_retVal[$i]; 204 $_tempEcho .= '|'; 205 } 206 echo str_replace( '||', '|', $_tempEcho ); 207 $retCount--; 208 echo PHP_EOL; 209 } 210 } 211 212 public function delete( $x ) 213 { 214 $this->_root = $this->_delete( $x, $this->_root ); 215 return $this->_root; 216 } 217 218 private function _delete( $val, $tree ) 219 { 220 if( $tree == null ) 221 return $tree; 222 223 if( $val > $tree->val ) { 224 $tree->right = $this->_delete( $val, $tree->right ); 225 if( $this->getHeight( $tree->right ) - $this->getHeight( $tree->left ) == 2 ) { 226 if( $val > $tree->right->val ) { 227 $tree = $this->singleRotateWithRight( $tree ); 228 }else { 229 $tree = $this->doubleRotateWithRight( $tree ); 230 } 231 } 232 }else if( $val < $tree->val ) { 233 $tree->left = $this->_delete( $val, $tree->left ); 234 if( $this->getHeight( $tree->left ) - $this->getHeight( $tree->right ) == 2 ) { 235 if( $val < $tree->left->val ) { 236 $tree = $this->singleRotateWithLeft( $tree ); 237 }else { 238 $tree = $this->doubleRotateWithLeft( $tree ); 239 } 240 } 241 242 }else { 243 if( $tree->left == null && $tree->right == null ) { 244 $tree = null; 245 return $tree; 246 } 247 if( $tree->left == null ) { 248 $tree = $tree->right; 249 }else if( $tree->right == null ) { 250 $tree = $tree->left; 251 }else { 252 $rightMin = $this->findMin( $tree->right ); 253 $tree->right = $this->_delete( $rightMin->val, $tree->right ); 254 $rightMin->left = $tree->left; 255 $rightMin->right = $tree->right; 256 257 $tree = $rightMin; 258 } 259 } 260 261 $tree->height = max( $this->getHeight( $tree->left ), $this->getHeight( $tree->right ) ) + 1; 262 return $tree; 263 } 264 } 265 266 267 $tree = new AvlTree(); 268 $tree->insert(3); 269 $tree->insert(2); 270 $tree->insert(1); 271 $tree->insert(4); 272 $tree->insert(5); 273 $tree->insert(6); 274 $tree->insert(7); 275 $tree->insert(16); 276 $tree->insert(15); 277 $tree->insert(14); 278 $tree->insert(13); 279 $tree->insert(12); 280 $tree->insert(11); 281 $tree->insert(10); 282 $tree->insert(8); 283 $tree->insert(9); 284 285 $tree->delete(7); 286 $tree->delete(8); 287 288 $tree->dump(); 289 // var_dump( $tree );
<?php $arr = range(1, 100 ); shuffle( $arr ); function insertSort( $arr ) { $count = count( $arr ); for( $i = 1; $i < $count; $i++ ) { $max = $arr[$i]; for( $j = $i; $j > 0 && $arr[$j-1] > $max; $j-- ) { $arr[$j] = $arr[$j-1]; } $arr[$j] = $max; } return $arr; } print_R( insertSort( $arr ) ); function shellSort( $arr ) { $count = count( $arr ); for( $step = $count >> 1; $step > 0; $step = $step >> 1 ) { for( $i = $step; $i < $count; $i++ ) { $max = $arr[$i]; for( $j = $i; $j - $step >= 0 && $arr[$j-$step] > $max; $j -= $step ) { $arr[$j] = $arr[$j-$step]; } $arr[$j] = $max; } } return $arr; } print_r( shellSort( $arr ) ); function down( &$arr, $position, $count ) { while( true ) { $val = $arr[$position]; $left = ( $position * 2 ) + 1; if( $left > $count - 1 ) break; $right = $left + 1; $maxkey = $left; if( $right < $count && $arr[$right] > $arr[$left] ) $maxkey = $right; if( $arr[$maxkey] > $val ) { $arr[$position] = $arr[$maxkey]; $arr[$maxkey] = $val; $position = $maxkey; }else break; } } //create heap function buildHeap( $arr ) { $count = count( $arr ); for( $i = ( $count >> 1 ) - 1; $i >= 0; $i-- ) { down( $arr, $i, $count ); } return $arr; } print_r( buildHeap( [1,2,3,4,5,6] ) ); function percDown( &$arr, $i, $count ) { $val = $arr[$i]; while( true ) { $left = $i * 2 + 1; if( $left > $count - 1 ) break; $right = $left + 1; $maxKey = $left; if( $right <= $count - 1 && $arr[$right] > $arr[$left] ) $maxKey = $right; if( $arr[$maxKey] > $val ) { $arr[$i] = $arr[$maxKey]; $i = $maxKey; }else break; } $arr[$i] = $val; } function heapSort( $arr ) { $count = count( $arr ); for( $i = $count >> 1; $i >=0; $i-- ) { percDown( $arr, $i, $count ); } for( $i = 0; $i < $count; $i++ ) { list( $arr[$count-$i-1], $arr[0] ) = [$arr[0], $arr[$count-$i-1]]; percDown( $arr, 0, $count-$i-1 ); } return $arr; } print_r( heapSort( $arr ) ); //归并 function mergeSort( $arr ) { $count = count( $arr ) -1 ; $temp = []; return _mergeSort( $arr, 0, $count, $temp ); } function _mergeSort( $arr, $start, $end, &$temp ) { if( $start == $end ) { return [$arr[$start]]; } $mid = ( $end + $start ) >> 1; $left = _mergeSort( $arr, $start, $mid, $temp ); $right = _mergeSort( $arr, $mid+1, $end, $temp ); $temp = []; $lc = count( $left ); $rc = count( $right ); $lp = $rp = 0; while( $lp < $lc && $rp < $rc ) { if( $left[$lp] < $right[$rp] ) { $temp[] = $left[$lp]; $lp++; }else if( $left[$lp] > $right[$rp] ) { $temp[] = $right[$rp]; $rp++; }else { $temp[] = $left[$lp]; $temp[] = $right[$rp]; $rp++; $lp++; } } while( $lp < $lc ) { $temp[] = $left[$lp]; $lp++; } while( $rp < $rc ) { $temp[] = $right[$rp]; $rp++; } return $temp; } // print_r( mergeSort( $arr ) ); function quickSort( $arr ) { $count = count( $arr ); _quickSort( $arr, 0, $count -1 ); return $arr; } function _quickSort( &$arr, $start, $end ) { if( $start >= $end ) { return; } $i = $start + 1; $j = $end; $pivot = $arr[$start]; while( true ) { while( $arr[$i] < $pivot && $i <= $j ) { $i++; } while( $arr[$j] > $pivot && $j >= $i ) { $j--; } if( $i < $j ) { list( $arr[$i], $arr[$j] ) = [$arr[$j], $arr[$i]]; $i++; $j--; }else { break; } } list( $arr[$j], $arr[$start] ) = [$arr[$start], $arr[$j]]; _quickSort( $arr, $start, $j - 1 ); _quickSort( $arr, $j + 1, $end ); } print_r( quickSort( [0,9,0,9,0,9,9,7,1] ) );