├── .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 |
5 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
34 |
35 |
36 |
37 |
38 | 1560271866007
39 |
40 |
41 | 1560271866007
42 |
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 |
--------------------------------------------------------------------------------