├── README.markdown ├── data_structure ├── queue │ ├── queue_using_spl.php │ ├── queue_using_array.php │ ├── README.markdown │ └── queue_using_class.php ├── stack │ ├── stack_using_spl.php │ ├── stack_using_array.php │ ├── README.markdown │ └── stack_using_class.php ├── linked_list │ ├── README.markdown │ ├── linked_list_using_spl.php │ └── linked_list_using_class.php └── tree │ └── binary_search_tree.php └── algorithm └── sort ├── bubble_sort.php ├── quick_sort.php ├── bucket_sort.php ├── radix_sort.php ├── insertion_sort.php ├── counting_sort.php ├── merge_sort.php └── heap_sort.php /README.markdown: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data_structure/queue/queue_using_spl.php: -------------------------------------------------------------------------------- 1 | enqueue("Element"); 13 | $queue->enqueue(23); 14 | $queue->enqueue(array(3, 4, 6)); 15 | 16 | while (!$queue->isEmpty()) { 17 | var_dump($queue->dequeue()); 18 | } 19 | 20 | if ($queue->isEmpty()) { 21 | // Element can be any type 22 | $queue->enqueue(new SplStack()); 23 | } 24 | 25 | // Throws RuntimeException if the queue is empty 26 | var_dump($queue->top()); 27 | -------------------------------------------------------------------------------- /data_structure/stack/stack_using_spl.php: -------------------------------------------------------------------------------- 1 | push("Element"); 13 | $stack->push(23); 14 | $stack->push(array(3, 4, 6)); 15 | 16 | while (!$stack->isEmpty()) { 17 | var_dump($stack->top()); 18 | $stack->pop(); 19 | } 20 | 21 | if ($stack->isEmpty()) { 22 | // Element can be any type 23 | $stack->push(new SplStack()); 24 | } 25 | 26 | // Throws RuntimeException if the stack is empty 27 | var_dump($stack->top()); 28 | -------------------------------------------------------------------------------- /data_structure/stack/stack_using_array.php: -------------------------------------------------------------------------------- 1 | = ($i + 1); $j--) { 16 | if ( $fn($elements[$j], $elements[$j-1]) ) { 17 | // swap the element 18 | $elements[$j] ^= $elements[$j-1]; 19 | $elements[$j-1] ^= $elements[$j]; 20 | $elements[$j] ^= $elements[$j-1]; 21 | } 22 | } 23 | } 24 | } 25 | 26 | function comparison_function(&$a, &$b) { 27 | return $a < $b; 28 | } 29 | 30 | // Example usage: 31 | $a = array(3, 5, 9, 8, 5, 7, 2, 1, 13); 32 | var_dump($a); 33 | bubble_sort($a); // Sort the elements 34 | var_dump($a); 35 | -------------------------------------------------------------------------------- /data_structure/stack/stack_using_class.php: -------------------------------------------------------------------------------- 1 | _data = array(); 16 | } 17 | 18 | /** 19 | * Check whether the stack empty or not. 20 | * 21 | * @return bool True if the stack is empty. 22 | */ 23 | public function is_empty() { 24 | return empty($this->_data); 25 | } 26 | 27 | public function top() { 28 | if (!$this->is_empty()) { 29 | return $this->_data[sizeof($this->_data) - 1]; 30 | } else { 31 | return null; 32 | } 33 | } 34 | 35 | /** 36 | * Push $el into the stack. 37 | * 38 | * @param mixed $el Element to be pushed. 39 | * @return void. 40 | */ 41 | public function push($el) { 42 | array_push($this->_data, $el); 43 | } 44 | 45 | /** 46 | * Pop the top element of the stack. 47 | * 48 | * @return mixed $element. 49 | */ 50 | public function pop() { 51 | if ($this->top() !== null) { 52 | return array_pop($this->_data); 53 | } 54 | return null; 55 | } 56 | } 57 | 58 | // Example usage: 59 | $stack = new Stack(); 60 | $stack->push("Element"); 61 | $stack->push(23); 62 | $stack->push(array(3, 4, 6)); 63 | 64 | while (!$stack->is_empty()) { 65 | var_dump($stack->top()); 66 | $stack->pop(); 67 | } 68 | 69 | // Outputs NULL 70 | var_dump($stack->top()); 71 | -------------------------------------------------------------------------------- /algorithm/sort/quick_sort.php: -------------------------------------------------------------------------------- 1 | _queue = array(); 16 | } 17 | 18 | /** 19 | * Check whether the queue empty or not. 20 | * 21 | * @return bool True if the queue is empty. 22 | */ 23 | public function is_empty() { 24 | return empty($this->_queue); 25 | } 26 | 27 | /** 28 | * Returns the front element in the queue. 29 | * 30 | * @return mixed The front element in the queue if exists, otherwise NULL. 31 | */ 32 | public function front() { 33 | if (!$this->is_empty()) { 34 | return $this->_queue[0]; 35 | } else { 36 | return null; 37 | } 38 | } 39 | 40 | /** 41 | * Enqueue $el into the queue. 42 | * 43 | * @param mixed $el Element to be enqueued. 44 | * @return void. 45 | */ 46 | public function enqueue($el) { 47 | array_push($this->_queue, $el); 48 | } 49 | 50 | /** 51 | * Dequeue the front element from the queue. 52 | * 53 | * @return mixed $element. 54 | */ 55 | public function dequeue() { 56 | if ($this->front() !== null) { 57 | return array_shift($this->_queue); 58 | } 59 | return null; 60 | } 61 | } 62 | 63 | // Example usage: 64 | $queue = new Queue(); 65 | $queue->enqueue("Element"); 66 | $queue->enqueue(23); 67 | $queue->enqueue(array(3, 4, 6)); 68 | 69 | while (!$queue->is_empty()) { 70 | echo "The front element is now : \n"; 71 | var_dump($queue->front()); 72 | echo "\n"; 73 | $queue->dequeue(); 74 | } 75 | 76 | // Outputs NULL 77 | var_dump($queue->front()); 78 | -------------------------------------------------------------------------------- /algorithm/sort/radix_sort.php: -------------------------------------------------------------------------------- 1 | $longest) { 31 | $longest = $el; 32 | } 33 | array_push($queues[$el % 10], $el); 34 | } 35 | 36 | // Queues are dequeued back into original elements. 37 | $i = 0; 38 | foreach ($queues as $key => $q) { 39 | while (!empty($queues[$key])) { 40 | $elements[$i++] = array_shift($queues[$key]); 41 | } 42 | } 43 | 44 | // Remaining iterations are determined based on longest digits element. 45 | $it = strlen($longest) - 1; 46 | $d = 10; 47 | while ($it--) { 48 | foreach ($elements as $el) { 49 | array_push($queues[floor($el/$d) % 10], $el); 50 | } 51 | 52 | $i = 0; 53 | foreach ($queues as $key => $q) { 54 | while (!empty($queues[$key])) { 55 | $elements[$i++] = array_shift($queues[$key]); 56 | } 57 | } 58 | $d *= 10; 59 | } 60 | } 61 | 62 | // Example usage: 63 | $a = array(170, 45, 75, 90, 802, 24, 2, 66); 64 | var_dump($a); 65 | radix_sort($a); 66 | var_dump($a); 67 | -------------------------------------------------------------------------------- /algorithm/sort/insertion_sort.php: -------------------------------------------------------------------------------- 1 | = 0 && $fn($key, $elements[$j]) ) { 34 | $elements[$j + 1] = $elements[$j]; // shift right 35 | $j = $j - 1; 36 | } 37 | $elements[$j + 1] = $key; 38 | } 39 | } 40 | 41 | /** 42 | * Comparison function used to compare each element. 43 | * @param mixed $a 44 | * @param mixed $b 45 | * @returns bool True iff $a is less than $b. 46 | */ 47 | function comparison_function(&$a, &$b) { 48 | return $a < $b; 49 | } 50 | 51 | 52 | // Example usage: 53 | $a = array(3, 5, 9, 8, 5, 7, 2, 1, 13); 54 | var_dump($a); 55 | insertion_sort($a); // Sort the elements 56 | var_dump($a); 57 | -------------------------------------------------------------------------------- /algorithm/sort/counting_sort.php: -------------------------------------------------------------------------------- 1 | = 0; $i--) { 53 | $sorted_elements[$temp_elements[$elements[$i]] - 1] = $elements[$i]; 54 | $temp_elements[$elements[$i]]--; 55 | } 56 | $elements = $sorted_elements; 57 | } 58 | 59 | // Example usage: 60 | $a = array(3, 5, 9, 8, 5, 7, 2, 1, 13, 2, 2, 4, 3, 1, 6); 61 | var_dump($a); 62 | counting_sort($a, 13); // Sort the elements, k = 13 63 | var_dump($a); 64 | -------------------------------------------------------------------------------- /data_structure/linked_list/linked_list_using_spl.php: -------------------------------------------------------------------------------- 1 | push(NULL); 18 | } 19 | 20 | public function insert($el) { 21 | $this->unshift($el); 22 | } 23 | 24 | public function delete($val) { 25 | $node = $this->search($val); 26 | 27 | if ($node === NULL) return; 28 | unset($this[$this->key()]); 29 | } 30 | 31 | public function search($val) { 32 | foreach ($this as $key => $node) { 33 | if ($node === $val) return $node; 34 | } 35 | return $node; 36 | } 37 | 38 | public function getPrev() { 39 | return ($this->key() - 1) >= 0 ? $this[$this->key() - 1] : 'NULL'; 40 | } 41 | 42 | public function getNext() { 43 | return $this[$this->key() + 1] !== NULL ? $this[$this->key() + 1] : 'NULL'; 44 | } 45 | } 46 | 47 | $LL = new LinkedList(); 48 | $LL->insert("Akeda"); 49 | $LL->insert("Dwi"); 50 | $LL->insert("Stevey"); 51 | $LL->insert("Paul"); 52 | 53 | // Function to test given keyword. 54 | function test_searching($keyword = '') { 55 | global $LL; 56 | 57 | if ($LL->search($keyword) !== NULL) { 58 | echo "Node with value '$keyword' is found\n"; 59 | echo "The previous node of '$keyword' is : " . $LL->getPrev() . "\n"; 60 | echo "The next node of '$keyword' is : " . $LL->getNext() . "\n"; 61 | } else { 62 | echo "Node with value '$keyword' is NOT found\n"; 63 | } 64 | echo "\n"; 65 | } 66 | 67 | // Test searching of node in linked list 68 | test_searching("Akeda"); 69 | test_searching("Someone else"); 70 | test_searching("Dwi"); 71 | test_searching("Paul"); 72 | 73 | // Delete Stevey 74 | $LL->delete("Stevey"); 75 | 76 | // The next and prev references were updated after delete operation. 77 | echo "After 'Stevey' is deleted: \n\n"; 78 | test_searching("Dwi"); 79 | test_searching("Paul"); 80 | -------------------------------------------------------------------------------- /algorithm/sort/merge_sort.php: -------------------------------------------------------------------------------- 1 | = 1; $i--) { 31 | // since we're sorting in ascending order, 32 | // we swap the highest-value element, that's in first index, 33 | // with lowest-value element, that's in last index. 34 | _swap_element($elements[0], $elements[$i]); 35 | // don't lookup again highest-value element 36 | // in [ i .. sizeof($elements) ] 37 | $_HEAP_SIZE--; 38 | _max_heapify($elements, 0, $fn); 39 | } 40 | } 41 | 42 | /** 43 | * Swap element $a and $b. 44 | * @param reference &$a Reference to element $a 45 | * @param reference &$b Reference to element $b 46 | * return void 47 | */ 48 | function _swap_element(&$a, &$b) { 49 | if ($a != $b) { 50 | $a ^= $b; 51 | $b ^= $a; 52 | $a ^= $b; 53 | } 54 | } 55 | 56 | function _build_max_heap(&$elements, $fn) { 57 | global $_HEAP_SIZE; 58 | 59 | $_HEAP_SIZE = sizeof($elements); 60 | $end = floor(sizeof($elements)/2); 61 | for ($i = $end; $i >= 0; $i--) { 62 | _max_heapify($elements, $i, $fn); 63 | } 64 | } 65 | 66 | /** 67 | * Reposition $elements[$i] into correct index based on heap property. 68 | * @param reference &$elements Reference to an array 69 | * @param int $i Index of particular element. 70 | * @return void 71 | */ 72 | function _max_heapify(&$elements, $i, $fn) { 73 | global $_HEAP_SIZE; 74 | 75 | $l = _left_child($i); 76 | $r = _right_child($i); 77 | if ($l < $_HEAP_SIZE && $fn($elements[$l], $elements[$i])) { 78 | $largest = $l; 79 | } else { 80 | $largest = $i; 81 | } 82 | if ($r < $_HEAP_SIZE && $fn($elements[$r], $elements[$largest])) { 83 | $largest = $r; 84 | } 85 | if ($largest != $i) { 86 | _swap_element($elements[$i], $elements[$largest]); 87 | _max_heapify($elements, $largest, $fn); 88 | } 89 | } 90 | 91 | /** 92 | * Get parent index given node index. 93 | * @param int $i Node index 94 | * @return int Parent node index 95 | */ 96 | function _parent_node($i) { 97 | return floor($i/2); 98 | } 99 | 100 | /** 101 | * Get left child index given node index. 102 | * @param int $i Node index. 103 | * @return int Left child index 104 | */ 105 | function _left_child($i) { 106 | return 2*$i; 107 | } 108 | 109 | /** 110 | * Get right child index given node index. 111 | * @param int $i Node index. 112 | * @param int Right child index 113 | */ 114 | function _right_child($i) { 115 | return 2*$i + 1; 116 | } 117 | 118 | // We use 'greater than' operator for max heap property 119 | // from largest to lowest. 120 | function comparison_function(&$a, &$b) { 121 | return $a > $b; 122 | } 123 | 124 | // Example usage: 125 | $a = array(3, 5, 9, 8, 5, 7, 2, 1, 13); 126 | var_dump($a); 127 | heap_sort($a); // Sort the elements 128 | var_dump($a); 129 | -------------------------------------------------------------------------------- /data_structure/tree/binary_search_tree.php: -------------------------------------------------------------------------------- 1 | _val = $el; 29 | } 30 | 31 | /** 32 | * Get node's value. 33 | * @access public 34 | * @return Node 35 | */ 36 | public function val() { 37 | return $this->_val; 38 | } 39 | 40 | /** 41 | * Get left-child's node. 42 | * @access public 43 | * @return Node 44 | */ 45 | public function left() { 46 | return $this->_left; 47 | } 48 | 49 | /** 50 | * Set left-child's node. 51 | * @access public 52 | * @return void 53 | */ 54 | public function setLeft(Node $node) { 55 | $this->_left = $node; 56 | } 57 | 58 | /** 59 | * Get right-child's node. 60 | * @access public 61 | * @return Node 62 | */ 63 | public function right() { 64 | return $this->_right; 65 | } 66 | 67 | /** 68 | * Set right-child's node. 69 | * @access public 70 | * @return void 71 | */ 72 | public function setRight(Node $node) { 73 | $this->_right = $node; 74 | } 75 | 76 | /** 77 | * Get parent's node. 78 | * @access public 79 | * @return Node 80 | */ 81 | public function parent() { 82 | return $this->_parent; 83 | } 84 | 85 | /** 86 | * Set parent's node. 87 | * @access public 88 | * @return public 89 | */ 90 | public function setParent(Node $node) { 91 | $this->_parent = $node; 92 | } 93 | 94 | public function __toString() { 95 | return $this->val() === NULL ? 'NULL' : $this->val() . ''; 96 | } 97 | } 98 | 99 | class BinarySearchTree { 100 | private $_root; 101 | private $_sentinel; 102 | 103 | public function __construct() { 104 | $this->_sentinel = new Node(NULL); 105 | 106 | $this->_root = $this->_sentinel; 107 | $this->_root->setParent($this->_sentinel); 108 | $this->_root->setLeft($this->_sentinel); 109 | $this->_root->setRight($this->_sentinel); 110 | } 111 | 112 | public function insert($val) { 113 | if (!is_object($val) || getclass($val) !== 'Node') { 114 | $newNode = new Node($val); 115 | } else { 116 | $newNode = $val; 117 | } 118 | $newNode->setLeft($this->_sentinel); 119 | $newNode->setRight($this->_sentinel); 120 | 121 | $node = $this->_root; 122 | $parent = $this->_sentinel; 123 | while ($node !== $this->_sentinel) { 124 | $parent = $node; 125 | if ($newNode->val() < $node->val()) { 126 | $node = $node->left(); 127 | } else { 128 | $node = $node->right(); 129 | } 130 | } 131 | 132 | if ($parent === $this->_sentinel) { 133 | $newNode->setParent($this->_sentinel); 134 | $this->_root = $newNode; 135 | } else { 136 | if ($newNode->val() < $parent->val()) { 137 | $parent->setLeft($newNode); 138 | } else { 139 | $parent->setRight($newNode); 140 | } 141 | $newNode->setParent($parent); 142 | } 143 | } 144 | 145 | public function search($val) { 146 | $node = $this->_root; 147 | 148 | while ($node !== $this->_sentinel && $node->val() !== $val) { 149 | if ($val < $node->val()) { 150 | $node = $node->left(); 151 | } else { 152 | $node = $node->right(); 153 | } 154 | } 155 | return $node; 156 | } 157 | } 158 | 159 | $BST = new BinarySearchTree; 160 | $BST->insert(15); 161 | $BST->insert(6); 162 | $BST->insert(18); 163 | $BST->insert(3); 164 | $BST->insert(7); 165 | $BST->insert(17); 166 | $BST->insert(20); 167 | $BST->insert(2); 168 | $BST->insert(4); 169 | $BST->insert(13); 170 | $BST->insert(9); 171 | 172 | function test_searching($num) { 173 | global $BST; 174 | 175 | $node = $BST->search($num); 176 | if ($node->val() !== NULL) { 177 | echo "Node with value $num is found\n"; 178 | echo "Parent's node = " . $node->parent() . "\n"; 179 | echo "Left-child's node = " . $node->left() . "\n"; 180 | echo "Right-child's node = " . $node->right() . "\n"; 181 | } else { 182 | echo "Node with value $num is NOT found\n"; 183 | } 184 | echo "\n"; 185 | } 186 | 187 | test_searching(7); 188 | test_searching(15); 189 | test_searching(3); 190 | test_searching(2); 191 | -------------------------------------------------------------------------------- /data_structure/linked_list/linked_list_using_class.php: -------------------------------------------------------------------------------- 1 | _val = $el; 21 | } 22 | 23 | public function val() { 24 | return $this->_val; 25 | } 26 | 27 | public function next() { 28 | return $this->_next; 29 | } 30 | 31 | public function setNext(Node $el) { 32 | $this->_next = $el; 33 | } 34 | 35 | public function prev() { 36 | return $this->_prev; 37 | } 38 | 39 | public function setPrev(Node $el) { 40 | $this->_prev = $el; 41 | } 42 | 43 | public function __toString() { 44 | return $this->val() === NULL ? 'NULL' : $this->val(); 45 | } 46 | } 47 | 48 | class LinkedList { 49 | /** 50 | * Head with Node-type object. 51 | */ 52 | private $_head; 53 | 54 | /** 55 | * Dummy Node-type object before the head and after the tail 56 | */ 57 | private $_sentinel; 58 | 59 | /** 60 | * All object initialized with NULL as its head. 61 | * 62 | * @return void 63 | */ 64 | public function __construct() { 65 | // Sentinel is dummy object before head and after tail. 66 | $sentinel = new Node(NULL); 67 | $sentinel->setNext($sentinel); 68 | $sentinel->setPrev($sentinel); 69 | 70 | $this->_sentinel = $sentinel; 71 | $this->_head = $this->_sentinel; 72 | } 73 | 74 | /** 75 | * Get dummy object value. It can be anything instead of NULL. 76 | */ 77 | public function sentinelVal() { 78 | return $this->_sentinel->val(); 79 | } 80 | 81 | /** 82 | * Insert $el into the list and make it as a head. 83 | * 84 | * @param mixed $val 85 | * @return void 86 | */ 87 | public function insert($val) { 88 | // Make sure element being inserted is type of Node. 89 | if (!is_object($val) || getclass($val) !== "Node") { 90 | $node = new Node($val); 91 | } else { 92 | $node = $val; 93 | } 94 | 95 | $this->_head->setPrev($node); 96 | 97 | $node->setNext($this->_head); 98 | $node->setPrev($this->_sentinel); 99 | $this->_head = $node; 100 | } 101 | 102 | /** 103 | * Delete element $el in linked list, if exists. 104 | * 105 | * @param mixed $val Element with value $val to be deleted. 106 | * @return void 107 | */ 108 | public function delete($val) { 109 | $node = $this->search($val); 110 | 111 | // Sentinel can't be deleted. 112 | if ($node->val() === $this->sentinelVal()) return; 113 | 114 | if ($node->prev()->val() !== $this->sentinelVal()) { 115 | $node->prev()->setNext($node->next()); 116 | } else { 117 | $this->_head = $node->next(); 118 | } 119 | 120 | if ($node->next() !== $this->sentinelVal()) { 121 | $node->next()->setPrev($node->prev()); 122 | } 123 | } 124 | 125 | /** 126 | * Search element in the singly-linked-list. 127 | * 128 | * @param mixed $val Element with value $val to be searched. 129 | * @return Node $el 130 | */ 131 | public function search($val) { 132 | $el = $this->_head; 133 | while ($el->val() !== $this->sentinelVal() && $el->val() !== $val) { 134 | $el = $el->next(); 135 | } 136 | 137 | return $el; 138 | } 139 | } 140 | 141 | $LL = new LinkedList(); 142 | $LL->insert("Akeda"); 143 | $LL->insert("Dwi"); 144 | $LL->insert("Stevey"); 145 | $LL->insert("Paul"); 146 | 147 | // Function to test given keyword. 148 | function test_searching($keyword = '') { 149 | global $LL; 150 | 151 | $node = $LL->search($keyword); 152 | if ($node->val() !== $LL->sentinelVal()) { 153 | echo "Node with value '$keyword' is found\n"; 154 | echo "The previous node of '$keyword' is : " . $node->prev() . "\n"; 155 | echo "The next node of '$keyword' is : " . $node->next() . "\n"; 156 | } else { 157 | echo "Node with value '$keyword' is NOT found\n"; 158 | } 159 | echo "\n"; 160 | } 161 | 162 | // Test searching of node in linked list 163 | test_searching("Akeda"); 164 | test_searching("Someone else"); 165 | test_searching("Dwi"); 166 | test_searching("Paul"); 167 | 168 | // Delete Stevey 169 | $LL->delete("Stevey"); 170 | 171 | // The next and prev references were updated after delete operation. 172 | echo "After 'Stevey' is deleted: \n\n"; 173 | test_searching("Dwi"); 174 | test_searching("Paul"); 175 | --------------------------------------------------------------------------------