├── .idea ├── The-Algorithms-PHP-JAVA.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── DataStructures ├── BinarySearchTree.php ├── DoublyLinkedList.php ├── Heap.php ├── SinglyLinkedList.java ├── SinglyLinkedList.php └── hashTable │ ├── BaseObj.php │ ├── FlexiHash.php │ ├── Readme.md │ ├── hashTable.php │ ├── hashTableLinear.php │ └── hashTableLink.php ├── LeetCode_Algorithms ├── 344.php ├── 349.php ├── 461.php ├── 476.php ├── 657.php ├── 728.php ├── 771.php ├── 804.php ├── 832.php ├── 905.php ├── 922.php ├── 929.php ├── 942.php ├── 961.php └── 977.php ├── Other ├── findHalfValue.php ├── mergeArr.c ├── mergeArr.php ├── reverseArr.php └── shuffle.php ├── Query └── BinarySearch.php ├── Sort ├── Base.php ├── BubbleSort.c ├── BubbleSort.php ├── HeapSort.php ├── InsertSort.php ├── MergeSort.php ├── QuickSort.php └── SelectSort.php └── readme.md /.idea/The-Algorithms-PHP-JAVA.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 34 | 35 | 36 | 37 | 38 | 1560271866007 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /DataStructures/BinarySearchTree.php: -------------------------------------------------------------------------------- 1 | left); 63 | $right = self::getSize($node->right); 64 | return 1+$left+$right; 65 | } 66 | 67 | public function size($node = null){ 68 | if($node == null){ 69 | return $this->doSize($this->root); 70 | }else{ 71 | return $this->doSize($node); 72 | } 73 | } 74 | 75 | private function doSize($node){ 76 | if($node == null){ 77 | return 0; 78 | }else{ 79 | return $node->N; 80 | } 81 | } 82 | 83 | //添加节点 84 | public function put($key,$val){ 85 | $this->root = $this->doPut($this->root,$key,$val); 86 | } 87 | 88 | private function doPut($node,$key,$val){ 89 | if($node == null){ 90 | return new Node($key,$val,1); 91 | } 92 | if($key < $node->key){ 93 | $node->left = $this->doPut($node->left,$key,$val); 94 | }elseif($key > $node->key){ 95 | $node->right = $this->doPut($node->right,$key,$val); 96 | }else{ 97 | $node->val = $val; 98 | } 99 | //沿着添加路径向上更新节点计数器的值 100 | $node->N = $this->doSize($node->left) + $this->doSize($node->right) + 1; 101 | return $node; 102 | } 103 | 104 | //获取key对应的值 105 | public function get($key){ 106 | return $this->doGet($this->root,$key); 107 | } 108 | 109 | private function doGet($node,$key){ 110 | if($node == null){ 111 | return null; 112 | } 113 | if($key < $node->key){ 114 | return $this->doGet($node->left,$key); 115 | }elseif($key > $node->key){ 116 | return $this->doGet($node->right,$key); 117 | }else{ 118 | return $node->val; 119 | } 120 | } 121 | 122 | //求树的深度 123 | public function getMaxDepth($node = null ){ 124 | if($node == null){ 125 | return $this->doGetMaxDepth($this->root); 126 | }else{ 127 | return $this->doGetMaxDepth($node); 128 | } 129 | } 130 | 131 | private function doGetMaxDepth($node){ 132 | if($node == null){ 133 | return 0; 134 | }else{ 135 | $left = $this->doGetMaxDepth($node->left); 136 | $right = $this->doGetMaxDepth($node->right); 137 | return 1+max($left,$right); 138 | } 139 | } 140 | 141 | //找最小的键 142 | public function min(){ 143 | if($this->root == null){ 144 | return null; 145 | } 146 | return $this->doMin($this->root)->val; 147 | } 148 | 149 | private function doMin($node){ 150 | if($node->left == null){ 151 | return $node; 152 | } 153 | return $this->doMin($node->left); 154 | } 155 | 156 | //二叉树转数组,中序遍历(先打印它的左子树,然后再打印它本身,最后打印它的右子树) 157 | private $print_tmp = []; 158 | public function printMiddle($node = null){ 159 | $this->print_tmp = []; 160 | if($node == null){ 161 | return $this->doPrintMiddle($this->root); 162 | }else{ 163 | return $this->doPrintMiddle($node); 164 | } 165 | } 166 | private function doPrintMiddle($node){ 167 | if($node == null){ 168 | return; 169 | } 170 | $this->doPrintMiddle($node->left); 171 | $this->print_tmp[$node->key] = $node->val; 172 | $this->doPrintMiddle($node->right); 173 | return $this->print_tmp; 174 | } 175 | //二叉树转数组,前序遍历(先打印这个节点,然后再打印它的左子树,最后打印它的右子树) 176 | public function printHead($node = null){ 177 | $this->print_tmp = []; 178 | if($node == null){ 179 | return $this->doPrintHead($this->root); 180 | }else{ 181 | return $this->doPrintHead($node); 182 | } 183 | } 184 | private function doPrintHead($node){ 185 | if($node == null){ 186 | return; 187 | } 188 | $this->print_tmp[$node->key] = $node->val; 189 | $this->doPrintHead($node->left); 190 | $this->doPrintHead($node->right); 191 | return $this->print_tmp; 192 | } 193 | //二叉树转数组,后序遍历(先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身) 194 | public function printBehind($node = null){ 195 | $this->print_tmp = []; 196 | if($node == null){ 197 | return $this->doPrintBehind($this->root); 198 | }else{ 199 | return $this->doPrintBehind($node); 200 | } 201 | } 202 | private function doPrintBehind($node){ 203 | if($node == null){ 204 | return; 205 | } 206 | $this->doPrintBehind($node->left); 207 | $this->doPrintBehind($node->right); 208 | $this->print_tmp[$node->key] = $node->val; 209 | return $this->print_tmp; 210 | } 211 | 212 | //二叉树翻转 213 | public function invertTree(){ 214 | $this->root = $this->doInvertTree($this->root); 215 | } 216 | private function doInvertTree($node){ 217 | if($node == null){ 218 | return null; 219 | } 220 | $node->left = $this->doInvertTree($node->left); 221 | $node->right = $this->doInvertTree($node->right); 222 | $tmp = $node->left; 223 | $node->left = $node->right; 224 | $node->right = $tmp; 225 | return $node; 226 | } 227 | //合并两个二叉树 228 | public static function mergeBST($t1,$t2){ 229 | $root = null; 230 | $res = self::doMergeBST($t1,$t2,$root); 231 | print_r($root); 232 | } 233 | private static function doMergeBST($t1,$t2,&$root){ 234 | if($t1!=null && $t2!=null){ 235 | $root = new Node($t1->key+$t2->key,$t1->val+$t2->val,1); 236 | $root->left = self::doMergeBST($t1->left,$t2->left,$root); 237 | $root->right = self::doMergeBST($t1->right,$t2->right,$root); 238 | $root->N = self::getSize($root); 239 | return; 240 | }else{ 241 | return $t1?$t1:$t2; 242 | } 243 | } 244 | 245 | //查找排名为第$key个的键的值 246 | public function select($k){ 247 | return $this->doSelect($this->root,$k); 248 | } 249 | 250 | private function doSelect($node,$k){ 251 | if($node == null){ 252 | return null; 253 | } 254 | $t = 0; 255 | if($node->left != null){ 256 | $t = $this->doSize($node->left); 257 | } 258 | if($t>$k){ 259 | return $this->doSelect($node->left,$k); 260 | }elseif($t<$k){ 261 | return $this->doSelect($node->right,$k-$t-1); 262 | }else{ 263 | return $node; 264 | } 265 | } 266 | public function rank($key){ 267 | return $this->doRank($this->root,$key); 268 | } 269 | private function doRank($node,$key){ 270 | if($node == null){ 271 | return 0; 272 | } 273 | if($key < $node->key){ 274 | return $this->doRank($node->left,$key); 275 | }elseif($key > $node->key){ 276 | $t = 0; 277 | if($node->left != null){ 278 | $t = $this->size($node->left); 279 | } 280 | return 1+$t + $this->doRank($node->right,$key); 281 | }else{ 282 | $t = 0; 283 | if($node->left != null){ 284 | $t = $this->size($node->left); 285 | } 286 | return $t; 287 | } 288 | } 289 | //删除最小的键 290 | public function deleteMin(){ 291 | $this->root = $this->doDeleteMin($this->root); 292 | } 293 | private function doDeleteMin($node){ 294 | if($node->left == null){ 295 | return $node->right; 296 | } 297 | $node->left = $this->doDeleteMin($node->left); 298 | $node->N = $this->doSize($node->left) + $this->doSize($node->right) + 1; 299 | return $node; 300 | } 301 | //删除二叉树的key对应的节点 302 | public function delete($key){ 303 | $this->root = $this->doDelete($this->root,$key); 304 | } 305 | private function doDelete($node,$key){ 306 | if($node == null){ 307 | return null; 308 | } 309 | if($node->key>$key){ 310 | $node->left = $this->doDelete($node->left,$key); 311 | }elseif($node->key<$key){ 312 | $node->right = $this->doDelete($node->right,$key); 313 | }else{ 314 | if($node->right == null){ 315 | return $node->left; 316 | } 317 | if($node->left == null){ 318 | return $node->right; 319 | } 320 | $t = $node; 321 | $node = $this->doMin($t->right); 322 | $node->right = $this->doDeleteMin($t->right); 323 | $node->left = $t->left; 324 | } 325 | $node->N = $this->doSize($node->left) + $this->doSize($node->right) + 1; 326 | return $node; 327 | } 328 | //判断是否是满二叉树 329 | public function isFullBST(){ 330 | $depth = $this->getMaxDepth(); //求高度 331 | $N = $this->root->N;//求节点数 332 | $trueN = pow(2,$depth)-1; //如果是满二叉树,那么节点数是2^k-1 333 | if($trueN == $N){ 334 | return true; 335 | } 336 | return false; 337 | } 338 | //判断是否是完全二叉树 339 | public function isCompleteBST(){ 340 | if($this->root == null){ 341 | return false; 342 | } 343 | $tmp = [$this->root];//模拟队列 344 | $flag = false; 345 | while(!empty($tmp)){ 346 | $node = array_shift($tmp); //移除最开头的元素 347 | $left = $node->left; 348 | $right = $node->right; 349 | if(($right!=null && $left==null) || ($flag && ($right!=null ||$left!=null ))){ 350 | return false; 351 | } 352 | if($left!=null){ 353 | array_push($tmp,$left); 354 | } 355 | if($right!=null){ 356 | array_push($tmp,$right); 357 | }else{ 358 | $flag = true; 359 | } 360 | } 361 | return true; 362 | } 363 | } 364 | class Node{ 365 | public $key; //键 366 | public $val; //值 367 | public $left; //左链接 368 | public $right; //右链接 369 | public $N = 0; //以该节点为根的子树的节点总数 370 | public function __construct($key,$val,$N){ 371 | $this->key = $key; 372 | $this->val = $val; 373 | $this->N = $N; 374 | } 375 | } 376 | $obj = new BST(); 377 | $obj->put(1,1); 378 | $obj->put(3,3); 379 | $obj->put(2,2); 380 | $obj->put(8,8); 381 | $obj->put(10,10); 382 | $obj->put(0,0); 383 | $obj->deleteMin(); 384 | var_dump($obj->select(0)); 385 | var_dump($obj->rank(101)); -------------------------------------------------------------------------------- /DataStructures/DoublyLinkedList.php: -------------------------------------------------------------------------------- 1 | isEmpty()){ 10 | $this->tail = $node; 11 | }else{ 12 | $this->head->previous = $node; 13 | } 14 | $node->next = $this->head; 15 | $this->head = $node; 16 | $this->count++; 17 | } 18 | //添加一个链表尾 19 | public function insertTail($data){ 20 | $node = new Node($data); 21 | if($this->isEmpty()){ 22 | $this->head = $node; 23 | }else{ 24 | $this->tail->next = $node; 25 | } 26 | $node->previous = $this->tail; 27 | $this->tail = $node; 28 | $this->count++; 29 | } 30 | public function insertOrder($data){ 31 | if(!$this->isEmpty()){ 32 | $tmp = $this->head; 33 | while($tmp != null && ($data > $tmp->data)){ 34 | $tmp = $tmp->next; 35 | } 36 | if($tmp == $this->head){ 37 | $this->insertHead($data); 38 | }elseif($tmp == null){ 39 | $this->insertTail($data); 40 | }else{ 41 | $node = new Node($data); 42 | $previous_tmp = $tmp->previous; 43 | $previous_tmp->next = $node; 44 | $node->next = $tmp; 45 | $node->previous = $previous_tmp; 46 | $this->count++; 47 | } 48 | }else{ 49 | $this->insertHead($data); 50 | } 51 | } 52 | public function deleteHead(){ 53 | if(!$this->isEmpty()){ 54 | $tmp = $this->head->next; 55 | if($tmp == null){ 56 | $this->tail = null; 57 | }else{ 58 | $tmp->previous = null; 59 | } 60 | $this->head = $tmp; 61 | $this->count--; 62 | } 63 | } 64 | public function deleteTail(){ 65 | if(!$this->isEmpty()){ 66 | $tmp = $this->tail->previous; 67 | if($tmp == null){ 68 | $this->head = null; 69 | }else{ 70 | $tmp->next = null; 71 | } 72 | $this->tail = $tmp; 73 | $this->count--; 74 | } 75 | } 76 | public function delete($data){ 77 | if(!$this->isEmpty()){ 78 | $tmp = $this->head; 79 | while($tmp->data != $data){ 80 | $tmp = $tmp->next; 81 | } 82 | if($tmp->previous == null){ 83 | $this->deleteHead(); 84 | }elseif($tmp->next == null){ 85 | $this->deleteTail(); 86 | }else{ 87 | $previous = $tmp->previous; 88 | $next = $tmp->next; 89 | $previous->next = $next; 90 | $next->previous = $previous; 91 | $this->count--; 92 | } 93 | } 94 | } 95 | public function __toString(){ 96 | $head = $this->head; 97 | $tail = $this->tail; 98 | $head_arr = []; 99 | $tail_arr = []; 100 | for($i=0;$icount/2));$i++){ 101 | $head_arr[] = $head->data; 102 | array_unshift($tail_arr, $tail->data); 103 | $head = $head->next; 104 | $tail = $tail->previous; 105 | } 106 | if($this->count % 2 != 0){ 107 | $head_arr[] = $head->data; 108 | } 109 | $res = array_merge($head_arr,$tail_arr); 110 | $res = implode($res, "->"); 111 | return $res; 112 | } 113 | public function isEmpty(){ 114 | return $this->head == null; 115 | } 116 | public function reverse(){ 117 | $tmp = null; 118 | $current = $this->head; 119 | $this->tail = $this->head; 120 | while($current != null){ 121 | $tmp = $current->previous; 122 | $current->previous = $current->next; 123 | $current->next = $tmp; 124 | $current = $current->previous; 125 | } 126 | if($tmp != null){ 127 | $this->head = $tmp->previous; 128 | } 129 | } 130 | } 131 | class Node{ 132 | public $next = null; 133 | public $previous = null; 134 | public $data; 135 | public function __construct($data){ 136 | $this->data = $data; 137 | } 138 | } 139 | $s = new DoublyLinkedList(); 140 | $s->insertHead(0); 141 | $s->insertHead(2); 142 | $s->insertHead(1); 143 | $s->insertTail(4); 144 | $s->reverse(); 145 | echo $s; 146 | $s->reverse(); 147 | echo "
"; 148 | echo $s; -------------------------------------------------------------------------------- /DataStructures/Heap.php: -------------------------------------------------------------------------------- 1 | arr = $arr; 7 | $this->count = count($arr); 8 | } 9 | public function run(){ 10 | $i = (int)(floor($this->count)/2); 11 | while($i--){ 12 | $this->createHeap($i); 13 | } 14 | } 15 | //初始化堆 16 | private function createHeap($i){ 17 | if($i>=$this->count){ 18 | return; 19 | } 20 | $left = 2*$i + 1; 21 | $right = $left + 1; 22 | $max = $i; 23 | if($left < $this->count && $this->arr[$left] > $this->arr[$max]){ 24 | $max = $left; 25 | } 26 | if($right < $this->count && $this->arr[$right] > $this->arr[$max]){ 27 | $max = $right; 28 | } 29 | if($i!=$max && $max<$this->count){ 30 | $this->swap($i,$max); 31 | $this->createHeap($max); 32 | } 33 | } 34 | 35 | public function insert($val){ 36 | $this->arr[$this->count] = $val; 37 | $this->count++; 38 | //将被插入元素放到末尾,然后上浮 39 | $this->swim($this->count-1); 40 | } 41 | 42 | private function swap($i,$j){ 43 | $tmp = $this->arr[$i]; 44 | $this->arr[$i] = $this->arr[$j]; 45 | $this->arr[$j] = $tmp; 46 | } 47 | 48 | //大根堆上浮 49 | private function swim($i){ 50 | if($i<1){ 51 | return; 52 | } 53 | //根节点位置 54 | $k = (int)(ceil($i/2))-1; 55 | if($this->arr[$i] > $this->arr[$k]){ 56 | $this->swap($i,$k); 57 | $this->swim($k); 58 | } 59 | } 60 | public function toArray(){ 61 | while($this->count){ 62 | $this->swap(0,--$this->count); 63 | $this->createHeap(0); 64 | } 65 | } 66 | } 67 | $heap = new Heap([10,6,5,1,12,9]); 68 | $heap->run(); 69 | $heap->insert(22); 70 | $heap->insert(8); 71 | $heap->insert(100); 72 | var_dump($heap->arr); -------------------------------------------------------------------------------- /DataStructures/SinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class SinglyLinkedList { 2 | private Node head; 3 | private int count; 4 | public void insertHead(int x) { 5 | Node newNode = new Node(x); 6 | newNode.next = head; 7 | head = newNode; 8 | ++count; 9 | } 10 | public void insertNth(int data,int position){ 11 | if (position < 0 || position > count) { 12 | throw new RuntimeException("position less than zero or position more than the count of list"); 13 | }else if(position == 0){ 14 | insertHead(data); 15 | }else{ 16 | Node node = new Node(data); 17 | Node tmp = head; 18 | for(int i = 0;inext = $this->head; 9 | $this->head = $node; 10 | $this->count++; 11 | } 12 | //向链表尾部添加新节点 13 | public function addNodeToTail(Node $node,$checkLoop = false){ 14 | $current = $this->head; 15 | if($current == null){//在链表为空的时候 16 | $this->head = $node; 17 | }else{ 18 | while($current->next != null){ 19 | $current = $current->next; 20 | } 21 | $current->next = $node; 22 | } 23 | if($checkLoop && $this->hasLoop()){ 24 | $current->next = null; 25 | }else{ 26 | while($node != null){ 27 | $this->count++; 28 | $node = $node->next; 29 | } 30 | } 31 | } 32 | //删除链表头元素 33 | public function deleteHead(): bool{ 34 | if($this->isEmpty()){ 35 | return false; 36 | } 37 | $this->head = $this->head->next; 38 | $this->count--; 39 | return true; 40 | } 41 | //判断链表是否为空 42 | public function isEmpty(): bool{ 43 | return $this->count == 0; 44 | } 45 | //遍历链表 46 | public function __toString(): string{ 47 | $res = ""; 48 | $node = $this->head; 49 | while($node != null){ 50 | $res .= $node->data . "->"; 51 | $node = $node->next; 52 | } 53 | $res = rtrim($res,"->"); 54 | return $res; 55 | } 56 | //向链表中的指定位置插入元素 57 | //如链表为1->2->3,执行insertNth(11,1);链表为11->1->2->3 58 | public function insertNth($data,$position){ 59 | if($position == 1){ 60 | $this->insertHead($data); 61 | }elseif($position < 1 || $position > $this->count+1){ 62 | return false; 63 | }else{ 64 | $tmp = new Node($data); 65 | $node = $this->head; 66 | for($i=0;$i<$position-2;$i++){ 67 | $node = $node->next; 68 | } 69 | $tmp->next = $node->next; 70 | $node->next = $tmp; 71 | $this->count++; 72 | } 73 | return true; 74 | } 75 | //删除链表中的指定位置 76 | //如果是1->2->3,deleteNth(1)为2->3 77 | public function deleteNth($position){ 78 | if($position < 1 || $position > $this->count){ 79 | return false; 80 | }elseif($position == 1){ 81 | $this->deleteHead(); 82 | }else{ 83 | $current = $this->head; 84 | for($i=0;$i<$position-2;$i++){ 85 | $current = $current->next; 86 | } 87 | $current->next = $current->next->next; 88 | $this->count--; 89 | } 90 | } 91 | //不知道节点总个数,找到单链表中间节点 92 | public function findMiddle(){ 93 | $slow = $this->head; 94 | $fast = $this->head; 95 | if($fast == null){ 96 | return false; 97 | } 98 | while($fast->next != null && $fast->next->next != null){ 99 | $slow = $slow->next; 100 | $fast = $fast->next->next; 101 | } 102 | if($fast->next != null){ 103 | return [ 104 | $slow->data, 105 | $slow->next->data 106 | ]; 107 | } 108 | return (array)($slow->data); 109 | } 110 | //找到环的入口 111 | public function findLoopStart(){ 112 | $hasLoop = false; 113 | $slow = $this->head; 114 | $fast = $this->head; 115 | if($fast == null){ 116 | return false; 117 | } 118 | while($fast->next != null && $fast->next->next != null){ 119 | $slow = $slow->next; 120 | $fast = $fast->next->next; 121 | if($slow == $fast){ 122 | $hasLoop = true; 123 | break; 124 | } 125 | } 126 | if($hasLoop){ 127 | $start = $this->head; 128 | while($start != $slow){ 129 | $start = $start->next; 130 | $slow = $slow->next; 131 | } 132 | return $start; 133 | }else{ 134 | return false; 135 | } 136 | } 137 | //求环的长度 138 | public function getCycleLength(){ 139 | if(($start = $this->findLoopStart()) != false){ 140 | $length = 0; 141 | $tmp = $start; 142 | while ($start != null) { 143 | $start = $start->next; 144 | $length++; 145 | if($start === $tmp){ 146 | return $length; 147 | } 148 | } 149 | } 150 | return false; 151 | } 152 | 153 | //判断是否有环 154 | public function hasLoop(){ 155 | $slow = $this->head; 156 | $fast = $this->head; 157 | if($fast == null){ 158 | return false; 159 | } 160 | while($fast->next != null && $fast->next->next != null){ 161 | $slow = $slow->next; 162 | $fast = $fast->next->next; 163 | if($slow === $fast){ 164 | return true; 165 | } 166 | } 167 | return false; 168 | } 169 | //删除排序链表中的重复元素 170 | public function deleteDuplicates(){ 171 | $tmp = $this->head; 172 | while($tmp->next!= null){ 173 | if($tmp->data == $tmp->next->data){ 174 | $tmp->next = $tmp->next->next; 175 | $this->count--; 176 | }else{ 177 | $tmp = $tmp->next; 178 | } 179 | } 180 | } 181 | //在两个链表无环的情况环判断是否相交 182 | //如果连个链表相交,那么两个链表就会呈Y型,只要判断最后一个节点是不是相等就行 183 | //1->2->3 184 | // \ 185 | // 9->10->11 186 | // 4->8/ 187 | public static function isJoinNoLoop1(Node $node1,Node $node2){ 188 | while($node1->next != null){ 189 | $node1 = $node1->next; 190 | } 191 | while($node2->next != null){ 192 | $node2 = $node2->next; 193 | } 194 | if($node1 === $node2){ 195 | return true; 196 | } 197 | return false; 198 | } 199 | //将第二个链表的头指向第一个链表的尾,然后判断是否有环 200 | public static function isJoinNoLoop2(Node $node1,Node $node2){ 201 | $tmp = $node1; 202 | while($tmp->next != null){ 203 | $tmp = $tmp->next; 204 | } 205 | //将第二个链表的头指向第一个链表的尾 206 | $tmp->next = $node2; 207 | $fast = $slow = $tmp; 208 | if($fast == null){ 209 | return false; 210 | } 211 | while($fast->next != null && $fast->next->next != null){ 212 | $slow = $slow->next; 213 | $fast = $fast->next->next; 214 | if($slow === $fast){ 215 | return true; 216 | } 217 | } 218 | return false; 219 | } 220 | //两个链表都有环,如果环入口相同则相交点在入口点前(只需计算着两个链表到入口点部分长度之差,然后用长的部分减去差,再同时与短的部分同步前进,如果节点相同,则为相交点),如果不同则相交点是任意两个入口点 221 | public static function bothLoop(Node $node1,Node $node2){ 222 | $start1 = self::findLoopStartStatic($node1); 223 | $start2 = self::findLoopStartStatic($node2); 224 | if($start1===$start2){ 225 | 226 | }else{ 227 | return [$start1,$start2]; 228 | } 229 | } 230 | private static function findLoopStartStatic(Node $node){ 231 | $hasLoop = false; 232 | $slow = $fast = $node; 233 | if($fast == null){ 234 | return false; 235 | } 236 | while($fast->next != null && $fast->next->next != null){ 237 | $slow = $slow->next; 238 | $fast = $fast->next->next; 239 | if($slow == $fast){ 240 | $hasLoop = true; 241 | break; 242 | } 243 | } 244 | if($hasLoop){ 245 | $start = $this->head; 246 | while($start != $slow){ 247 | $start = $start->next; 248 | $slow = $slow->next; 249 | } 250 | return $start; 251 | }else{ 252 | return false; 253 | } 254 | } 255 | //找到两个有交点的链表的交点 256 | public static function getFirstJoinNode(Node $node1,Node $node2){ 257 | $tmp1 = $node1; 258 | $tmp2 = $node2; 259 | $length1 = $length2 = 0; 260 | while($tmp1->next != null){ 261 | $length1++; 262 | $tmp1 = $tmp1->next; 263 | } 264 | while($tmp2->next != null){ 265 | $length2++; 266 | $tmp2 = $tmp2->next; 267 | } 268 | if($length1>$length2){ 269 | $tmp = $node1; 270 | for($i=0;$i<$length1-$length2;$i++){ 271 | $tmp = $tmp->next; 272 | } 273 | while($tmp->next!=null && $node2->next!=null){ 274 | $tmp = $tmp->next; 275 | $node2=$node2->next; 276 | if($tmp===$node2){ 277 | return $tmp; 278 | } 279 | } 280 | }else{ 281 | $tmp = $node2; 282 | for($i=0;$i<$length2-$length1;$i++){ 283 | $tmp = $tmp->next; 284 | } 285 | $tmp = $tmp->next; 286 | $node1=$node1->next; 287 | if($tmp===$node1){ 288 | return $tmp; 289 | } 290 | } 291 | } 292 | 293 | //链表翻转 294 | public function reverse(): void{ 295 | $current = $this->head; 296 | $tmp = null; 297 | $res = null; 298 | while($current != null){ 299 | $tmp = $current->next; 300 | $current->next = $res; 301 | $res = $current; 302 | $current = $tmp; 303 | } 304 | $this->head = $res; 305 | } 306 | //在不知道链表长度的情况下,查出倒数第N个节点 307 | public function findLastNode($position){ 308 | if($position<1){ 309 | return 0; 310 | } 311 | $slow = $fast = $this->head; 312 | for($i=0;$i<$position-1;$i++){ 313 | if($fast->next != null){ 314 | $fast = $fast->next; 315 | }else{ 316 | return null; 317 | } 318 | } 319 | while($fast->next != null){ 320 | $fast = $fast->next; 321 | $slow = $slow->next; 322 | } 323 | return $slow; 324 | } 325 | //合并两个有序的单链表,合并之后还是有序 326 | public static function mergeLinkList(Node $node1,Node $node2){ 327 | if($node1 == null && $node2 == null){ 328 | return null; 329 | } 330 | if($node1 == null){ 331 | return $node2; 332 | } 333 | if($node2 == null){ 334 | return $node1; 335 | } 336 | $res = null; 337 | $current = null; 338 | if($node1->data < $node2->data){ 339 | $res = $node1; 340 | $current = $node1; 341 | $node1 = $node1->next; 342 | }else{ 343 | $res = $node2; 344 | $current = $node2; 345 | $node2 = $node2->next; 346 | } 347 | while($node1 != null && $node2 != null){ 348 | if($node1->data < $node2->data){ 349 | $current->next = $node1; 350 | $node1 = $node1->next; 351 | }else{ 352 | $current->next = $node2; 353 | $node2 = $node2->next; 354 | } 355 | $current = $current->next; 356 | } 357 | while($node1 != null){ 358 | $current->next = $node1; 359 | $node1 = $node1->next; 360 | $current = $current->next; 361 | } 362 | while($node2 != null){ 363 | $current->next = $node2; 364 | $node2 = $node2->next; 365 | $current = $current->next; 366 | } 367 | $echo = ""; 368 | while($res != null){ 369 | $echo .= $res->data."->"; 370 | $res = $res->next; 371 | } 372 | $echo = rtrim($echo,"->"); 373 | echo $echo; 374 | } 375 | //删除一个给定的节点,该节点在链表中,时间复杂度O(1) 376 | public static function deleteNode(Node $head,Node $node){ 377 | if($node->next != null){//删除的不是尾节点 378 | $node->data = $node->next->data; 379 | $node->next = $node->next->next; 380 | }elseif($node == $head){ //链表只有一个节点 381 | $head = null; 382 | }else{ //删除尾节点 383 | $current = $head; 384 | while($current->next != $node){ 385 | $current = $current->next; 386 | } 387 | $current->next = null; 388 | } 389 | return $head; 390 | } 391 | } 392 | class Node{ 393 | public $data; 394 | public $next; 395 | public function __construct($data){ 396 | $this->data = $data; 397 | } 398 | } 399 | $s1 = new SinglyLinkedList(); 400 | $s2 = new SinglyLinkedList(); 401 | $common = new SinglyLinkedList(); 402 | $s1->insertHead(8); 403 | $s1->insertHead(6); 404 | $s1->insertHead(4); 405 | $s1->insertHead(1); 406 | $common->insertHead(1); 407 | $common->insertHead(9); 408 | $common->insertHead(10); 409 | $s1->addNodeToTail($common->head); 410 | $s2->insertHead(3); 411 | $s2->insertHead(2); 412 | $s2->insertHead(1); 413 | $s2->addNodeToTail($common->head); 414 | $res = SinglyLinkedList::isJoinNoLoop2($s1->head,$s2->head); 415 | var_dump($res); -------------------------------------------------------------------------------- /DataStructures/hashTable/BaseObj.php: -------------------------------------------------------------------------------- 1 | _replicas;$i++){ 20 | $hash = $this->hashing($server.$i); 21 | $this->_positionToTarget[$hash] = $server; 22 | $this->_targetToPositions[$server][] = $hash; 23 | } 24 | $this->_positionToTargetSorted = false; 25 | $this->_targetCount++; 26 | return true; 27 | } 28 | 29 | public function addTargets($server){ 30 | foreach ($servers as $server){ 31 | $this->addTarget($server); 32 | } 33 | 34 | return true; 35 | } 36 | 37 | public function lookup($key){ 38 | if (empty($this->_positionToTarget)){ 39 | return array(); 40 | } 41 | if ($this->_targetCount == 1){ 42 | //取第一个 43 | return key($this->_targetToPositions); 44 | } 45 | $resourceHash = $this->hashing($key); 46 | $this->_sortPositionTargets(); 47 | foreach ($this->_positionToTarget as $hash => $server){ 48 | // start collecting targets after passing resource position 49 | if ($hash > $resourceHash){ 50 | return $server; 51 | } 52 | } 53 | } 54 | 55 | private function _sortPositionTargets(){ 56 | if (!$this->_positionToTargetSorted){ 57 | ksort($this->_positionToTarget, SORT_REGULAR); 58 | $this->_positionToTargetSorted = true; 59 | } 60 | } 61 | 62 | public function getAllTargets(){ 63 | return array_keys($this->_targetToPositions); 64 | } 65 | 66 | public function removeTarget($server){ 67 | if (!isset($this->_targetToPositions[$server])){ 68 | return; 69 | } 70 | 71 | foreach ($this->_targetToPositions[$server] as $hash){ 72 | unset($this->_positionToTarget[$hash]); 73 | } 74 | 75 | unset($this->_targetToPositions[$server]); 76 | 77 | $this->_targetCount--; 78 | 79 | return true; 80 | } 81 | 82 | public function getPosisionToTarger(){ 83 | return $this->_positionToTarget; 84 | } 85 | 86 | public function getTargetToPositions(){ 87 | return $this->_targetToPositions; 88 | } 89 | } 90 | $obj = new FlexiHash(); 91 | $obj->addTarget("127.0.0.1:6379"); 92 | $obj->addTarget("127.0.0.1:6378"); 93 | $obj->addTarget("127.0.0.1:6380"); 94 | $obj->addTarget("127.0.0.1:6381"); 95 | $res = $obj->lookup("aa111bc1"); 96 | print_r($obj->getPosisionToTarger()); 97 | print_r($obj->getTargetToPositions()); 98 | -------------------------------------------------------------------------------- /DataStructures/hashTable/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DataStructures/hashTable/hashTable.php: -------------------------------------------------------------------------------- 1 | size = $size; 11 | //SplFixedArray是一个不会根据key做hash的数组 12 | $this->buckets = new SplFixedArray($this->size); 13 | } 14 | 15 | //生成hash码 16 | public function hashing($key){ 17 | $hash = crc32($key)%$this->size; 18 | if($hash<0){//注意不能为负,因为SplFixedArray不能插入负 19 | return $hash+$this->size; 20 | } 21 | return $hash; 22 | } 23 | 24 | //添加 25 | public function insertHash($key, $value){ 26 | $index = $this->hashing($key); 27 | if(!isset($this->buckets[$index])){ 28 | $this->used++; 29 | } 30 | $this->buckets[$index] = $value; 31 | return true; 32 | } 33 | 34 | public function findHash($key){ 35 | $index = $this->hashing($key); 36 | if(isset($this->buckets[$index])){ 37 | return $this->buckets[$index]; 38 | } 39 | return NULL; 40 | } 41 | 42 | public function deleteHash($key){ 43 | $index = $this->hashing($key); 44 | if(isset($this->buckets[$index])){ 45 | $this->used--; 46 | unset($this->buckets[$index]); 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | public function displayHashtable(){ 53 | return (array)$this->buckets; 54 | } 55 | 56 | public function issetHash($key){ 57 | $index = $this->hashing($key); 58 | if(isset($this->buckets[$index])){ 59 | return true; 60 | } 61 | return false; 62 | } 63 | 64 | //获取负载因子 65 | public function getLoadFactor(){ 66 | return number_format($this->used/$this->size,2); 67 | } 68 | 69 | public function offsetExists($key){ 70 | return $this->issetHash($key); 71 | } 72 | 73 | public function offsetGet($key){ 74 | return $this->findHash($key); 75 | } 76 | 77 | public function offsetSet($key,$val){ 78 | $this->insertHash($key,$val); 79 | } 80 | 81 | public function offsetUnset($key){ 82 | return $this->deleteHash($key); 83 | } 84 | } 85 | $obj = new HashTable(); 86 | $obj["a"] = "a"; 87 | $obj["b"] = "b"; 88 | $obj[1] = 1; 89 | $obj[1.9] = 1.9; 90 | unset($obj["a"]); 91 | var_dump($obj["a"]); 92 | $res = $obj->displayHashtable(); 93 | var_dump($res); 94 | var_dump($obj->getLoadFactor()); -------------------------------------------------------------------------------- /DataStructures/hashTable/hashTableLinear.php: -------------------------------------------------------------------------------- 1 | N,需要依靠数组中的空位解决hash冲突 5 | 开放地址最简单的方法叫做线性探测法:当碰撞发生时候,直接检查散列表中下一个位置(将索引值+1) 6 | 1.命中,该位置的键和被查找的键相同 7 | 2.未命中,键为空 8 | 3.继续查找,该位置的键和被查找的键不同 9 | 在继续查找的过程中,如果到底数组结尾时候这回数组的开头,直到找到该键或者遇到一个空元素 10 | */ 11 | class hashTableLinear{ 12 | public $size; 13 | public $keys; 14 | public $vals; 15 | public $used = 0; 16 | 17 | public function __construct($size = 4){ 18 | $this->keys = new SplFixedArray($size); 19 | $this->vals = new SplFixedArray($size); 20 | $this->size = $size; 21 | } 22 | 23 | public function hashing($key){ 24 | $hash = crc32($key)%$this->size; 25 | if($hash<0){//注意不能为负,因为SplFixedArray不能插入负 26 | return $hash+$this->size; 27 | } 28 | return $hash; 29 | } 30 | 31 | public function insertHash($key,$val){ 32 | if($this->getLoadFactor()>=1){ 33 | $this->resize(2*$this->size); 34 | } 35 | $start = $hash = $this->hashing($key); 36 | do{ 37 | if($this->keys[$hash] === $key){ 38 | $this->vals[$hash] = $val; 39 | return true; 40 | } 41 | $hash=($hash+1)%$this->size; 42 | }while($this->keys[$hash]!=null); 43 | $this->keys[$hash] = $key; 44 | $this->vals[$hash] = $val; 45 | $this->used++; 46 | } 47 | public function findHash($key){ 48 | $start = $hash = $this->hashing($key); 49 | $loop = false;//是否已经走了一圈了 50 | do{ 51 | if($this->keys[$hash] === $key){ //防止 0==null为true 52 | return $this->vals[$hash]; 53 | } 54 | if($loop){//已经走了一圈了,但是还没找到 55 | return false; 56 | } 57 | $hash=($hash+1)%$this->size; 58 | if($hash == $start){ 59 | $loop = true;//已经走了一圈了 60 | } 61 | }while($this->keys[$hash]!=null); 62 | return false; 63 | } 64 | 65 | //直接将该键所在位置设置为null是不行的,因为会是的在此位置之后的元素无法被查找到 66 | public function deleteHash($key){ 67 | if($this->getLoadFactor()>0 && $this->getLoadFactor()<=0.5){ 68 | $this->resize($this->size/2); 69 | } 70 | $start = $hash = $this->hashing($key); 71 | while($this->keys[$hash]!==$key){ 72 | $hash = ($hash+1)%$this->size; 73 | if($hash == $start){ 74 | return false; //防止死循环 75 | } 76 | } 77 | $this->keys[$hash] = null; 78 | $this->vals[$hash] = null; 79 | $hash = ($hash+1)%$this->size; 80 | while($this->keys[$hash]!==null){ 81 | $key = $this->keys[$hash]; 82 | $val = $this->vals[$hash]; 83 | $this->keys[$hash] = null; 84 | $this->vals[$hash] = null; 85 | $this->used--; 86 | $this->insertHash($key,$val); 87 | $hash = ($hash+1)%$this->size; 88 | } 89 | $this->used--; 90 | } 91 | 92 | //获取负载因子 93 | public function getLoadFactor(){ 94 | return number_format($this->used/$this->size,2); 95 | } 96 | 97 | public function resize($size){ 98 | $new_hashTableLinear = new hashTableLinear($size); 99 | for($i=0;$i<$this->size;$i++){ 100 | if($this->keys[$i] != null){ 101 | $new_hashTableLinear->insertHash($this->keys[$i],$this->vals[$i]); 102 | } 103 | } 104 | $this->size = $size; 105 | $this->used = $new_hashTableLinear->used; 106 | $this->keys = $new_hashTableLinear->keys; 107 | $this->vals = $new_hashTableLinear->vals; 108 | } 109 | } 110 | $obj = new hashTableLinear(); 111 | $obj->insertHash(8,1); 112 | $obj->insertHash(4,2); 113 | $obj->insertHash(0,0); 114 | $obj->insertHash(3,3); 115 | $obj->deleteHash(4); 116 | $obj->deleteHash(3); 117 | $obj->deleteHash(0); 118 | $obj->insertHash(3,3); 119 | $obj->insertHash(7,7); 120 | var_dump($obj->used); 121 | var_dump($obj->keys); -------------------------------------------------------------------------------- /DataStructures/hashTable/hashTableLink.php: -------------------------------------------------------------------------------- 1 | buckets = new SplFixedArray($size); 11 | for($i=0;$i<$size;$i++){ 12 | $this->buckets[$i] = new LinkedList(); 13 | } 14 | $this->size = $size; 15 | } 16 | 17 | public function hashing($key){ 18 | $hash = crc32($key)%$this->size; 19 | if($hash<0){//注意不能为负,因为SplFixedArray不能插入负 20 | return $hash+$this->size; 21 | } 22 | return $hash; 23 | } 24 | 25 | public function insertHash($key,$val){ 26 | if($this->getLoadFactor()>=1.5){ 27 | $this->resize(2*$this->size); 28 | } 29 | $hash = $this->hashing($key); 30 | $res = $this->buckets[$hash]->insert($key,$val); 31 | if($res){ 32 | $this->used++; 33 | } 34 | } 35 | 36 | public function deleteHash($key){ 37 | if($this->getLoadFactor()>0 && $this->getLoadFactor()<=0.5){ 38 | $this->resize($this->size/2); 39 | } 40 | $hash = $this->hashing($key); 41 | $res = $this->buckets[$hash]->delete($key); 42 | if($res){ 43 | $this->used--; 44 | } 45 | } 46 | 47 | public function issetHash($key){ 48 | $index = $this->hashing($key); 49 | return $this->buckets[$index]->isset($key); 50 | } 51 | 52 | public function findHash($key){ 53 | $index = $this->hashing($key); 54 | return $this->buckets[$index]->find($key); 55 | } 56 | 57 | public function displayHashtable(){ 58 | for($i=0;$i<$this->size;$i++){ 59 | $res = $this->buckets[$i]->display(); 60 | var_dump($res); 61 | } 62 | } 63 | public function resize($size){ 64 | $new_HashTableLink = new HashTableLink($size); 65 | for($i=0;$i<$this->size;$i++){ 66 | $node_info = $this->buckets[$i]->getAllNodeInfo(); 67 | foreach($node_info as $node){ 68 | $new_HashTableLink -> insertHash($node[0],$node[1]); 69 | } 70 | } 71 | $this->size = $size; 72 | $this->buckets = $new_HashTableLink->buckets; 73 | $this->used = $new_HashTableLink->used; 74 | } 75 | //获取负载因子 76 | public function getLoadFactor(){ 77 | return number_format($this->used/$this->size,2); 78 | } 79 | 80 | public function offsetExists($key){ 81 | return $this->issetHash($key); 82 | } 83 | 84 | public function offsetGet($key){ 85 | return $this->findHash($key); 86 | } 87 | 88 | public function offsetSet($key,$val){ 89 | return $this->insertHash($key,$val); 90 | } 91 | 92 | public function offsetUnset($key){ 93 | return $this->deleteHash($key); 94 | } 95 | } 96 | class LinkedList{ 97 | public $head; 98 | public $size = 0; 99 | public function insert($key,$val){ 100 | $node = new Node($key,$val); 101 | if($this->head == null){ 102 | $this->head = $node; 103 | }else{ 104 | //需要遍历链表,防止插入相同的键 105 | $current = $this->head; 106 | while($current!=null){ 107 | if($current->key == $key){ 108 | $current->val = $val; 109 | return false; 110 | } 111 | $current = $current->next; 112 | } 113 | $node->next = $this->head; 114 | $this->head = $node; 115 | } 116 | $this->size++; 117 | return true; 118 | } 119 | 120 | public function find($key){ 121 | $current = $this->head; 122 | while($current!=null){ 123 | if($current->key == $key){ 124 | return $current->val; 125 | } 126 | $current = $current->next; 127 | } 128 | return false; 129 | } 130 | 131 | public function delete($key){ 132 | if($this->size == 0){ 133 | return false; 134 | }else{ 135 | $hasDelete = false; 136 | $current = $this->head; 137 | if($current->key == $key){ 138 | $this->head = $current->next; 139 | $hasDelete = true; 140 | }else{ 141 | while($current->next!=null){ 142 | if($current->next->key == $key){ 143 | $current->next = $current->next->next; 144 | $hasDelete = true; 145 | break; 146 | } 147 | $current = $current->next; 148 | } 149 | } 150 | if($hasDelete){ 151 | $this->size--; 152 | return true; 153 | } 154 | return false; 155 | } 156 | } 157 | 158 | public function isset($key){ 159 | if($this->size == 0){ 160 | return false; 161 | }else{ 162 | $current = $this->head; 163 | if($current->key == $key){ 164 | return true; 165 | }else{ 166 | while($current->next!=null){ 167 | if($current->next->key == $key){ 168 | return true; 169 | } 170 | $current = $current->next; 171 | } 172 | } 173 | return false; 174 | } 175 | } 176 | 177 | public function display(){ 178 | $res = ""; 179 | $tmp = $this->head; 180 | while($tmp!=null){ 181 | $res.="{$tmp->val}->"; 182 | $tmp=$tmp->next; 183 | } 184 | $res = rtrim($res,"->"); 185 | return $res; 186 | } 187 | public function getAllNodeInfo(){ 188 | $res = []; 189 | $current = $this->head; 190 | while($current!=null){ 191 | $res[] = [$current->key,$current->val]; 192 | $current = $current->next; 193 | } 194 | return $res; 195 | } 196 | } 197 | class Node{ 198 | public $key; 199 | public $val; 200 | public $next; 201 | public function __construct($key,$val){ 202 | $this->key = $key; 203 | $this->val = $val; 204 | } 205 | } 206 | 207 | $obj = new HashTableLink(); 208 | $obj["a"] = 123; 209 | $obj["b"] = 2; 210 | $obj["c"] = "c"; 211 | $obj["a"] = "88"; 212 | unset($obj["b"]); 213 | for($i=0;$i<30000;$i++){ 214 | $obj[mt_rand(-10000,10000)] = mt_rand(-10000,10000); 215 | } 216 | $obj->displayHashtable(); -------------------------------------------------------------------------------- /LeetCode_Algorithms/344.php: -------------------------------------------------------------------------------- 1 | add($nums1[$i]); 16 | } 17 | 18 | 19 | for ($i = 0; $i < count($nums2); $i++) { 20 | if ($hashTable1->contains($nums2[$i])) { 21 | $rs[$nums2[$i]] = $nums2[$i]; 22 | } 23 | } 24 | 25 | return $rs; 26 | 27 | } 28 | } 29 | 30 | class HashSet 31 | { 32 | public $data = []; 33 | private const BUCKET = 5; 34 | 35 | /** 36 | * Initialize your data structure here. 37 | */ 38 | function __construct() { 39 | 40 | } 41 | 42 | /** 43 | * @param Integer $key 44 | * @return NULL 45 | */ 46 | function add($key) { 47 | $this->data[$this->hash($key)][$key] = $key; 48 | } 49 | 50 | /** 51 | * @param Integer $key 52 | * @return NULL 53 | */ 54 | function remove($key) { 55 | if ($this->contains($key)) { 56 | unset($this->data[$this->hash($key)][$key]); 57 | } 58 | } 59 | 60 | /** 61 | * Returns true if this set contains the specified element 62 | * @param Integer $key 63 | * @return Boolean 64 | */ 65 | function contains($key) { 66 | if (isset($this->data[$this->hash($key)][$key])) { 67 | return true; 68 | } 69 | 70 | return false; 71 | } 72 | 73 | public function hash($key) 74 | { 75 | return $key % self::BUCKET; 76 | } 77 | } 78 | $obj = new Solution(); 79 | $res = $obj -> intersection([1,2,3,4,5,6,6],[4,6,7,4,8,9]); 80 | var_dump($res); -------------------------------------------------------------------------------- /LeetCode_Algorithms/461.php: -------------------------------------------------------------------------------- 1 | =$item){ 8 | $res.=chr($item+32); 9 | }else{ 10 | $res.=$str[$i]; 11 | } 12 | } 13 | return $res; 14 | } 15 | } -------------------------------------------------------------------------------- /LeetCode_Algorithms/804.php: -------------------------------------------------------------------------------- 1 | ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]; 4 | function uniqueMorseRepresentations($words) { 5 | $bak_arr = []; 6 | foreach ($words as $item) { 7 | $bak_str = ""; 8 | $len = strlen($item); 9 | for($i=0;$i<$len;$i++){ 10 | $bak_str .= self::MORSE[ord($item[$i])]; 11 | } 12 | $bak_arr[$bak_str] = null; 13 | } 14 | return count($bak_arr); 15 | } 16 | } -------------------------------------------------------------------------------- /LeetCode_Algorithms/832.php: -------------------------------------------------------------------------------- 1 | =0){ 28 | $res[] = $arr[$posIndex]*$arr[$posIndex]; 29 | $posIndex--; 30 | } 31 | return $res; 32 | } 33 | } -------------------------------------------------------------------------------- /Other/findHalfValue.php: -------------------------------------------------------------------------------- 1 | =0&&($arr[$j]>$tmp)){ 33 | $arr[$j+1] = $arr[$j]; 34 | $j--; 35 | } 36 | if($j != $i-1){ 37 | $arr[$j+1] = $tmp; 38 | } 39 | } 40 | return $arr[($count/2)]; 41 | } 42 | $arr = []; 43 | $count = 1000; 44 | $index = mt_rand(0,$count/2); 45 | $data = mt_rand(-10000,10000); 46 | for($i=0;$i<$count;$i++){ 47 | if($i == $index){ 48 | for($j=0;$j<501;$j++){ 49 | $arr[] = $data; 50 | } 51 | $i = $j+$i-1; 52 | }else{ 53 | $arr[] = mt_rand(-10000,10000); 54 | } 55 | } 56 | var_dump(search1($arr)); 57 | var_dump(search2($arr)); -------------------------------------------------------------------------------- /Other/mergeArr.c: -------------------------------------------------------------------------------- 1 | #include 2 | void mergeArr(int a[],int len_a,int b[],int len_b,int res[]){ 3 | int x,y,z = 0; 4 | while(x$index){ 15 | $right = $center - 1; 16 | }elseif($arr[$center]<$index){ 17 | $left = $center + 1; 18 | }else{ 19 | return $center; 20 | } 21 | } 22 | } 23 | function search2(Array $arr,$index){ 24 | $right = count($arr); 25 | $left = 0; 26 | while($left<=$right){ 27 | $center = (int)($left+floor($right-$left)/2); //不会有溢出风险 28 | if($arr[$center]>$index){ 29 | $right = $center - 1; 30 | }elseif($arr[$center]<$index){ 31 | $left = $center + 1; 32 | }else{ 33 | return $center; 34 | } 35 | } 36 | } 37 | //给定一个升序数组,数组可以有重复元素,找到最左的元素下标 38 | function search_find1(Array $arr,$index){ 39 | $right = count($arr); 40 | $left = 0; 41 | while($left<=$right){ 42 | $center = (int)(floor($right+$left)/2); 43 | if(!isset($arr[$center])){ 44 | return null; 45 | } 46 | if($arr[$center] >= $index){ //降序的话就是<= 47 | $right = $center - 1; 48 | }else{ 49 | $left = $center + 1; 50 | } 51 | } 52 | if($left < count($arr) && $arr[$left] == $index){ 53 | return $left; 54 | } 55 | return null; 56 | } 57 | //给定一个升序数组,数组可以有重复元素,找到最右的元素下标(有bug,在[1,1]下找1会null) 58 | function search_find2(Array $arr,$index){ 59 | $right = count($arr); 60 | $left = 0; 61 | while($left<=$right){ 62 | $center = (int)(floor($right+$left)/2); 63 | if(!isset($arr[$center])){ 64 | return null; 65 | } 66 | if($arr[$center] <= $index){ 67 | $left = $center + 1; 68 | }else{ 69 | $right = $center - 1; 70 | } 71 | } 72 | if($right < count($arr) && $arr[$right] == $index){ 73 | return $right; 74 | } 75 | return null; 76 | } 77 | //https://www.cnblogs.com/luoxn28/p/5767571.html 78 | $tmp = []; 79 | for($i=0;$i<100000;$i++){ 80 | $tmp[] = $i; 81 | } 82 | $index = mt_rand(0,100000); 83 | $start = microtime(true); 84 | $res = search1($tmp,$index); 85 | echo microtime(true) - $start; 86 | -------------------------------------------------------------------------------- /Sort/Base.php: -------------------------------------------------------------------------------- 1 | count = $count; 10 | $this->createArr(); 11 | $this->start_time = microtime(true); 12 | } 13 | public function createArr(){ 14 | for($i=0;$i<$this->count;$i++){ 15 | $this->arr[] = mt_rand(-self::MAX_INT,self::MAX_INT); 16 | } 17 | } 18 | public function elapsedTime(){ 19 | echo number_format(microtime(true) - $this->start_time,4); 20 | } 21 | 22 | public function swap($first,$second){ 23 | $tmp = $this->arr[$first]; 24 | $this->arr[$first] = $this->arr[$second]; 25 | $this->arr[$second] = $tmp; 26 | } 27 | public function less($first,$second){ 28 | if($first>$second){ 29 | return true; 30 | } 31 | return false; 32 | } 33 | public function check(){ 34 | for($i=0;$i<$this->count-1;$i++){ 35 | if($this->arr[$i] > $this->arr[$i+1]){ 36 | return false; 37 | } 38 | } 39 | return true; 40 | } 41 | } -------------------------------------------------------------------------------- /Sort/BubbleSort.c: -------------------------------------------------------------------------------- 1 | #include 2 | int BubbleSort(int arr[],int len); 3 | void swap(int *arr1,int *arr2); 4 | int main(){ 5 | int arr[] = {3,5,7,11,32,4,1,78,95,23,14,6}; 6 | int len = sizeof(arr)/sizeof(arr[0]); 7 | BubbleSort(arr,len); 8 | for(int i=0;i arr[y+1]){ 16 | swap(&arr[y],&arr[y+1]); 17 | /* 18 | int temp = arr[y]; 19 | arr[y] = arr[y+1]; 20 | arr[y+1] = temp; 21 | */ 22 | } 23 | } 24 | } 25 | } 26 | void swap(int *arr1,int *arr2){ 27 | int temp = *arr1; 28 | *arr1 = *arr2; 29 | *arr2 = temp; 30 | } 31 | -------------------------------------------------------------------------------- /Sort/BubbleSort.php: -------------------------------------------------------------------------------- 1 | count-1;$i++){ 16 | for($j=0;$j<$this->count-$i-1;$j++){ 17 | if($this->less($this->arr[$j],$this->arr[$j+1])){ 18 | $this->swap($j,$j+1); 19 | } 20 | } 21 | } 22 | } 23 | //对冒泡排序的优化 24 | public function sort2(){ 25 | $count = $this->count; 26 | do{ 27 | $swap = false; 28 | for($i=0;$i<$count - 1;$i++){ 29 | if($this->less($this->arr[$i],$this->arr[$i+1])){ 30 | $this->swap($i,$i+1); 31 | $swap = true; 32 | } 33 | } 34 | $count--; 35 | }while($swap); 36 | } 37 | } 38 | function BubbleSortFunc1(Array $arr){ 39 | $count = count($arr); 40 | for($i=0;$i<$count-1;$i++){ 41 | //冒泡在数组部分有序的情况下,还是要循环多次 42 | for($j=0;$j<$count-$i-1;$j++){ 43 | //冒泡对数组的交换次数比较多 44 | if($arr[$j] > $arr[$j+1]){ 45 | $tmp = $arr[$j]; 46 | $arr[$j] = $arr[$j+1]; 47 | $arr[$j+1] = $tmp; 48 | } 49 | } 50 | } 51 | return $arr; 52 | } 53 | //对冒泡排序的优化,如果一次循环发现数组已经有序则不需要再次循环,直接返回 54 | function BubbleSortFunc2(Array $arr){ 55 | $count = count($arr); 56 | do{ 57 | $swap = false; 58 | for($i=0;$i<$count - 1;$i++){ 59 | if($arr[$i] > $arr[$i+1]){ 60 | $tmp = $arr[$i]; 61 | $arr[$i] = $arr[$i+1]; 62 | $arr[$i+1] = $tmp; 63 | $swap = true; 64 | } 65 | } 66 | $count--; 67 | }while($swap); 68 | return $arr; 69 | } 70 | //test1 71 | $sort = new BubbleSort(10); 72 | $arr = $sort->arr; 73 | $sort->sort1(); 74 | $sort->elapsedTime(); 75 | var_dump($sort->check()); 76 | var_dump($sort->arr); 77 | //test2 78 | $sort = new BubbleSort(10); 79 | $sort->sort2(); 80 | $sort->elapsedTime(); 81 | var_dump($sort->check()); 82 | var_dump($sort->arr); 83 | //test3 84 | $res = BubbleSortFunc1($arr); 85 | var_dump($res); 86 | //test4 87 | $res = BubbleSortFunc2($arr); 88 | var_dump($res); 89 | 90 | -------------------------------------------------------------------------------- /Sort/HeapSort.php: -------------------------------------------------------------------------------- 1 | arr = $arr; 27 | $this->order = $order; 28 | $this->find = $find; 29 | $this->count = count($arr); 30 | } 31 | public function run(){ 32 | $this->createHeap(); 33 | if($this->find == 1){ 34 | return (array)$this->arr[0]; 35 | } 36 | $t = $this->find; 37 | while($this->count && $t--){ 38 | $this->swap(0,--$this->count); 39 | $this->buildHeap(0,$this->count); 40 | } 41 | return array_slice($this->arr,$this->count,$this->find); 42 | } 43 | private function createHeap(){ 44 | $i = (int)(floor($this->count)/2); 45 | while($i--){ 46 | $this->buildHeap($i,$this->count); 47 | } 48 | } 49 | private function buildHeap($i,$count){ 50 | if($i>=$count){ 51 | return; 52 | } 53 | //根位置是0,不是1 54 | $left = 2*$i+1; 55 | $right = $left+1; 56 | $max = $i; 57 | if($left < $count && $this->less($left,$max)){ 58 | $max = $left; 59 | } 60 | if($right < $count && $this->less($right,$max)){ 61 | $max = $right; 62 | } 63 | if($max != $i && $max<$count){ 64 | $this->swap($max,$i); 65 | $this->buildHeap($max,$count); 66 | } 67 | 68 | } 69 | private function less($i,$j){ 70 | if($this->order == self::ORDER_ASC){ 71 | return $this->arr[$i] > $this->arr[$j]; 72 | }else{ 73 | return $this->arr[$i] < $this->arr[$j]; 74 | } 75 | } 76 | private function swap($i,$j){ 77 | $tmp = $this->arr[$i]; 78 | $this->arr[$i] = $this->arr[$j]; 79 | $this->arr[$j] = $tmp; 80 | } 81 | } 82 | class HeapSort2{ 83 | public $arr; 84 | private $count; 85 | public function __construct(Array $arr){ 86 | $this->arr = $arr; 87 | $this->count = count($arr); 88 | } 89 | public function run(){ 90 | $i = (int)(floor($this->count)/2); 91 | while($i--){ 92 | $this->buildHeap($i,$this->count); 93 | } 94 | while($this->count){ 95 | $this->swap(0,--$this->count); 96 | $this->buildHeap(0,$this->count); 97 | } 98 | } 99 | private function buildHeap($i,$count){ 100 | if($i>=$count){ 101 | return; 102 | } 103 | //根位置是0,不是1 104 | $left = 2*$i+1; 105 | $right = $left+1; 106 | $max = $i; 107 | if($left < $count && $this->less($left,$max)){ 108 | $max = $left; 109 | } 110 | if($right < $count && $this->less($right,$max)){ 111 | $max = $right; 112 | } 113 | if($max != $i && $max<$count){ 114 | $this->swap($max,$i); 115 | $this->buildHeap($max,$count); 116 | } 117 | 118 | } 119 | private function less($i,$j){ 120 | return $this->arr[$i] > $this->arr[$j]; 121 | } 122 | private function swap($i,$j){ 123 | $tmp = $this->arr[$i]; 124 | $this->arr[$i] = $this->arr[$j]; 125 | $this->arr[$j] = $tmp; 126 | } 127 | } 128 | //测试堆排序找最大或者最小的前几个 129 | $tmp = []; 130 | for($i=0;$i<100;$i++){ 131 | $tmp[] = $i; 132 | } 133 | //查找最小的前10个 134 | $obj = new HeapSort1($tmp,10,HeapSort1::ORDER_DESC); 135 | $res = $obj->run(); 136 | var_dump($res); 137 | //查找最大的前3个 138 | $obj = new HeapSort1($tmp,3,HeapSort1::ORDER_ASC); 139 | $res = $obj->run(); 140 | var_dump($res); 141 | 142 | 143 | //测试堆排序 144 | $tmp = []; 145 | for($i=0;$i<1000;$i++){ 146 | $tmp[] = mt_rand(-100000,100000); 147 | } 148 | $obj = new HeapSort2($tmp); 149 | $obj->run(); 150 | var_dump($obj->arr); -------------------------------------------------------------------------------- /Sort/InsertSort.php: -------------------------------------------------------------------------------- 1 | count;$i++){ 12 | $j = $i - 1; 13 | $tmp = $this->arr[$i]; 14 | while($j>=0&&$this->less($this->arr[$j],$tmp)){ 15 | $this->arr[$j+1] = $this->arr[$j]; 16 | $j--; 17 | } 18 | $this->arr[$j+1] = $tmp; 19 | } 20 | } 21 | } 22 | function InsertSortFunc(array $arr){ 23 | $len = count($arr); 24 | for($i=1;$i<$len;$i++){ 25 | $temp = $arr[$i]; 26 | $j = $i - 1; 27 | while($j>=0&&$arr[$j]>$temp){ 28 | $arr[$j+1] = $arr[$j]; 29 | $j--; 30 | } 31 | $arr[$j+1] = $temp; 32 | } 33 | return $arr; 34 | } 35 | $sort = new InsertSort(1000); 36 | $arr = $sort->arr; 37 | $sort->sort(); 38 | $sort->elapsedTime(); 39 | var_dump($sort->check()); 40 | var_dump($sort->arr); -------------------------------------------------------------------------------- /Sort/MergeSort.php: -------------------------------------------------------------------------------- 1 | mSort(0,$this->count-1); 32 | } 33 | 34 | private function mSort($left,$right) 35 | { 36 | if($left<$right){ 37 | $center = (int)floor(($left+$right)/2); 38 | $this->mSort($left,$center); 39 | $this->mSort($center+1,$right); 40 | $this->merge($left,$center,$right); 41 | } 42 | } 43 | private function merge($left,$center,$right) 44 | { 45 | $min = $left; 46 | $max = $center + 1; 47 | //归并排序最大的问题就是空间复杂度,所需要的空间和N成正比 48 | $tmp = []; 49 | while($min <= $center && $max <= $right){ 50 | if($this->less($this->arr[$max],$this->arr[$min])){ 51 | $tmp[] = $this->arr[$min++]; 52 | }else{ 53 | $tmp[] = $this->arr[$max++]; 54 | } 55 | } 56 | while($min<=$center){ 57 | $tmp[] = $this->arr[$min++]; 58 | } 59 | while($max<=$right){ 60 | $tmp[] = $this->arr[$max++]; 61 | } 62 | for($i=0;$iarr[$left+$i] = $tmp[$i]; 64 | } 65 | } 66 | } 67 | 68 | //原地归并优化 69 | final class mergeSort2 extends Base 70 | { 71 | public $tmp = []; 72 | public function __construct($count){ 73 | parent::__construct($count); 74 | $this->mSort(0,$this->count-1); 75 | } 76 | 77 | private function mSort($left,$right) 78 | { 79 | if($left<$right){ 80 | $center = (int)floor(($left+$right)/2); 81 | $this->mSort($left,$center); 82 | $this->mSort($center+1,$right); 83 | $this->merge($left,$center,$right); 84 | } 85 | } 86 | private function merge($left,$center,$right) 87 | { 88 | $min = $left; 89 | $max = $center + 1; 90 | for($i=$left;$i<=$right;$i++){ 91 | $this->tmp[$i] = $this->arr[$i]; 92 | } 93 | for($j=$left;$j<=$right;$j++){ 94 | if($min>$center){ 95 | $this->arr[$j] = $this->tmp[$max++]; 96 | }elseif($max>$right){ 97 | $this->arr[$j] = $this->tmp[$min++]; 98 | }elseif($this->less($this->tmp[$min],$this->tmp[$max])){ 99 | $this->arr[$j] = $this->tmp[$max++]; 100 | }else{ 101 | $this->arr[$j] = $this->tmp[$min++]; 102 | } 103 | } 104 | } 105 | } 106 | //自底向上优化 107 | class merge{ 108 | public $arr; 109 | public function __construct(Array $arr){ 110 | $this->arr = $arr; 111 | for($i=1;$imerge($j,$j+$i-1,min($j+2*$i-1,count($arr)-1)); 114 | } 115 | } 116 | } 117 | private function merge($left,$center,$right){ 118 | $min = $left; 119 | $max = $center+1; 120 | $tmp = []; 121 | while($min<=$center && $max<=$right){ 122 | if($this->arr[$min]<$this->arr[$max]){ 123 | $tmp[] = $this->arr[$min++]; 124 | }else{ 125 | $tmp[] = $this->arr[$max++]; 126 | } 127 | } 128 | while($min<=$center){ 129 | $tmp[] = $this->arr[$min++]; 130 | } 131 | while($max<=$right){ 132 | $tmp[] = $this->arr[$max++]; 133 | } 134 | for($i=0;$iarr[$left+$i] = $tmp[$i]; 136 | } 137 | } 138 | } 139 | class m{ 140 | public $arr; 141 | public function __construct($arr){ 142 | $this->arr = $arr; 143 | $this->doSort(0,count($arr)-1); 144 | } 145 | public function doSort($left,$right){ 146 | if($left<$right){ 147 | $center = (int)(floor($left+$right)/2); 148 | $this->doSort($left,$center); 149 | $this->doSort($center+1,$right); 150 | if($this->arr[$center]>$this->arr[$center+1]){ 151 | $this->merge($left,$center,$right); 152 | } 153 | } 154 | } 155 | public function merge($left,$center,$right){ 156 | $min = $left; 157 | $max = $center+1; 158 | $tmp = []; 159 | while($min<=$center && $max<=$right){ 160 | if($this->arr[$min] < $this->arr[$max]){ 161 | $tmp[] = $this->arr[$min++]; 162 | }else{ 163 | $tmp[] = $this->arr[$max++]; 164 | } 165 | } 166 | while($min<=$center){ 167 | $tmp[] = $this->arr[$min++]; 168 | } 169 | while($max<=$right){ 170 | $tmp[] = $this->arr[$max++]; 171 | } 172 | for($i=0;$iarr[$left+$i] = $tmp[$i]; 174 | } 175 | } 176 | } 177 | // $sort = new mergeSort1(10000); 178 | // var_dump($sort->check()); 179 | // $sort->elapsedTime(); 180 | 181 | $sort = new mergeSort2(10000); 182 | var_dump($sort->check()); 183 | $sort->elapsedTime(); -------------------------------------------------------------------------------- /Sort/QuickSort.php: -------------------------------------------------------------------------------- 1 | =0 && ($arr[$j]>$tmp)){ 80 | $arr[$j+1] = $arr[$j]; 81 | $j--; 82 | } 83 | $arr[$j+1] = $tmp; 84 | } 85 | return $arr; 86 | } 87 | $flag = $arr[0]; 88 | $left = $right = []; 89 | for($i=1;$i<$count;$i++){ 90 | if($arr[$i]<$flag){ 91 | $left[] = $arr[$i]; 92 | }else{ 93 | $right[] = $arr[$i]; 94 | } 95 | } 96 | $left = quickSort3($left); 97 | $right = quickSort3($right); 98 | return array_merge($left,(array)$flag,$right); 99 | } 100 | $temp = []; 101 | for($i=0;$i<1000;$i++){ 102 | $temp[] = mt_rand(0,1000); 103 | } 104 | $count = count($temp) + 1; 105 | ini_set("xdebug.max_nesting_level",$count); 106 | var_dump(QuickSort1($temp)); 107 | ini_set("xdebug.max_nesting_level",256); -------------------------------------------------------------------------------- /Sort/SelectSort.php: -------------------------------------------------------------------------------- 1 | count-1;$i++){ 13 | $min = $i; 14 | for($j=$i+1;$j<$this->count;$j++){ 15 | if($this->less($this->arr[$min],$this->arr[$j])){ 16 | $min = $j; 17 | } 18 | } 19 | if($min != $i){ 20 | $this->swap($i,$min); 21 | } 22 | } 23 | } 24 | } 25 | 26 | function SelectSortFunc1(Array $arr){ 27 | $count = count($arr); 28 | for($i=0;$i<$count-1;$i++){ 29 | $min = $i; 30 | for($j=$i+1;$j<$count;$j++){ 31 | if($arr[$min]>$arr[$j]){ 32 | $min = $j; 33 | } 34 | } 35 | if($min != $i){ 36 | $tmp = $arr[$min]; 37 | $arr[$min] = $arr[$i]; 38 | $arr[$i] = $tmp; 39 | } 40 | } 41 | return $arr; 42 | } 43 | function SelectSortFunc2(Array $arr){ 44 | $count = count($arr); 45 | for($left=0,$right=$count-1;$left<$right;$left++,$right--){ 46 | $min = $left; 47 | $max = $right; 48 | for($i=$left;$i<=$right;$i++){ 49 | if($arr[$i] < $arr[$min]){ 50 | $min = $i; 51 | }elseif($arr[$i] > $arr[$max]){ 52 | $max = $i; 53 | } 54 | } 55 | if($min != $left){ 56 | $tmp = $arr[$min]; 57 | $arr[$min] = $arr[$left]; 58 | $arr[$left] = $tmp; 59 | } 60 | if($max == $left){//因为$arr[$left]值已经改变了 61 | $max = $min; 62 | } 63 | if($max != $right){ 64 | $tmp = $arr[$max]; 65 | $arr[$max] = $arr[$right]; 66 | $arr[$right] = $tmp; 67 | } 68 | } 69 | return $arr; 70 | } 71 | $sort = new SelectSort(10000); 72 | $sort->sort(); 73 | $sort->elapsedTime(); 74 | var_dump($sort->check()); 75 | var_dump($sort->arr); 76 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## 排序 2 | * [冒泡排序] 3 | * [选择排序] 4 | * [插入排序] 5 | * [归并排序] 6 | * [快速排序] 7 | * [堆排序] 8 | 9 | ||冒泡|优化冒泡|选择|优化选择|插入|归并|快排|堆排序| 10 | |:---|:---|:---|:---|:---|:---|:---|:---|:---| 11 | |100|0.00023|0.000277|0.000098|0.000082|0.000104|0.000192|0.00014|0.00019| 12 | |1000|0.02423|0.02597|0.01434|0.0127|0.01208|0.0026|0.0006|0.00308| 13 | |10000|2.3718|2.3178|1.0359|0.8146|0.8587|0.0222|0.01236|0.03449| 14 | |50000|61.638|59.470|25.337|20.426|21.491|0.1248|0.09279|0.22093| 15 | |100000|244.389|236.38|101.58|81.64|86.95|0.267|0.3982|0.4647| 16 | 17 | |topK找最大前100个|堆排序| 18 | |:---|:---| 19 | |100000|0.0327| 20 | 21 | ## 查找 22 | * [二分查找] 23 | * [二叉树查找] 24 | ## 数据结构 25 | * [单向链表] 26 | * 向链表头添加元素 27 | * 向链表尾部添加新节点 28 | * 删除链表头元素 29 | * 判断链表是否为空 30 | * 遍历链表 31 | * 向链表中的指定位置插入元素 32 | * 删除链表中的指定位置 33 | * 不知道节点总个数,找到单链表中间节点 34 | * 找到环的入口 35 | * 求环的长度 36 | * 判断是否有环 37 | * 删除排序链表中的重复元素 38 | * 在两个链表无环的情况环判断是否相交 39 | * 在两个链表有环的情况环判断是否相交 40 | * 找到两个有交点的链表的交点 41 | * 链表翻转 42 | * 在不知道链表长度的情况下,查出倒数第N个节点 43 | * 合并两个有序的单链表 44 | * 删除一个给定的节点,该节点在链表中,时间复杂度O(1) 45 | * [双向链表] 46 | * [二叉堆] 47 | * [搜索二叉树] 48 | * 添加值 49 | * 获取key对应的值 50 | * 获取最小key对应的值 51 | * 翻转 52 | * 合并两个二叉树 53 | * 查找排名为第N个的键的值 54 | * 求高度 55 | * 遍历(前、中、后序) 56 | * 删除最小键 57 | * 删除一个给定的key对应的节点 58 | * 判断是否是完全二叉树 59 | * 判断是否是满二叉树 60 | * [虚拟节点一致性hash] 61 | * [hash表] 62 | * 不解决冲突 63 | * 拉链法解决冲突 64 | * 线性探测法解决冲突 65 | 66 | --------------------------------------------------------------------------------