(4)樸素字符串匹配node
Class StringMatch { /** * 樸素字符串匹配,在目標t匹配模式p第一次出現的位置 * @param $t target 目標 * @param $p pattern 模式 */ public function find($t, $p) { $t_len = strlen($t); $p_len = strlen($p); if ($t_len < $p_len) { return -1; } $i = 0; //t遊標 $j = 0; //p遊標 while ($i < $t_len - $p_len + 1) { while ($j < $p_len && $t[$i] == $p[$j]) { $i++; $j++; } if ($j == $p_len) { return $i - $p_len; } else { $i = $i - $j + 1; $j = 0; } } return -1; } /** * 樸素字符串匹配,在目標t匹配模式p出現的全部位置 * @param $t * @param $p */ public function findAll($t, $p) { $t_len = strlen($t); $p_len = strlen($p); if ($t_len < $p_len) { return -1; } $i = 0; //t遊標 $j = 0; //p遊標 $ret_arr = array(); while ($i < $t_len - $p_len + 1) { while ($j < $p_len && $t[$i] == $p[$j]) { $i++; $j++; } if ($j == $p_len) { $ret_arr[] = $i - $p_len; } $i = $i - $j + 1; $j = 0; } return $ret_arr; } } $match_obj = new StringMatch(); $t = "abcdefgdefgg"; $p = "de"; $a = $match_obj->find($t, $p); var_dump($a); $b = $match_obj->findAll($t, $p); var_dump($b);
(5)不帶括號的四則運算器this
Class SimpleCalculator { const OP_ADD = '+'; const OP_SUB = '-'; const OP_MUL = '*'; const OP_DIV = '/'; const OP_TOTAL_SET = ['+', '-', '*', '/']; /** * 不帶括號的四則運算器 * @param $exp */ public function calculate($exp) { $exp_arr = $this->_splitExp($exp); if (empty($exp_arr)) { return 0; } if (count($exp_arr) == 1) { return $exp_arr[0]; } $num1 = $exp_arr[0]; $op = ''; $num2 = null; $i = 1; while ($i < count($exp_arr)) { $cur_op = $exp_arr[$i++]; $cur_num = $exp_arr[$i++]; if ($cur_op == self::OP_ADD || $cur_op == self::OP_SUB) { //若是是加減操做符 //判斷op num2是否存在 //若是存在,計算num1 op num2的結果做num1,當前操做符作op,當前操做數作num2 //若是不存在,當前操做符做op,當前操做數做num2 if ($op != '') { $num1 = $this->_operateNums($num1, $num2, $op); } $op = $cur_op; $num2 = $cur_num; } else { //若是是乘除操做符 //判斷op num2存在 //若是存在(op優先級必定比cur_op低),計算num2 cur_op cur_num做num2 //若是不存在,計算num1 cur_op cur_num做num1 if ($op != '') { $num2 = $this->_operateNums($num2, $cur_num, $cur_op); } else { $num1 = $this->_operateNums($num1, $cur_num, $cur_op); } } } return isset($num2) ? $this->_operateNums($num1, $num2, $op) : $num1; } /** * 拆分表達式元素 * @param $exp * 返回結果有三種狀況: * [] //表達式錯誤或者爲空 * 一個元素 //表達式只有一個數字 * 多個元素 //普通表達式,相似3+5*7 */ private function _splitExp($exp) { $str = ''; $i = 0; $len = strlen($exp); $exp_arr = []; while ($i < $len) { while (($i < $len) && (('0' <= $exp[$i] && $exp[$i] <= '9') || $exp[$i] == '.')) { $str .= $exp[$i]; $i++; } if ($str == '') { //無操做數說明表達式錯誤 A return []; } $num = floatval($str); $exp_arr[] = $num; $str = ''; if ($i < $len) { if (in_array($exp[$i], self::OP_TOTAL_SET)) { $exp_arr[] = $exp[$i]; $i++; } else { //無操做符說明表達式錯誤 B return []; } } } //A B只能保證一個操做數後邊跟着一個操做符,不能保證最後的元素是操做數,此處判斷一下 if (in_array(end($exp_arr), self::OP_TOTAL_SET)) { return []; } return $exp_arr; } /**this * @param $num1 * @param $num2 * @param $ope * @return float|int */ private function _operateNums($num1, $num2, $ope) { $num = 0; switch ($ope) { case self::OP_ADD: $num = $num1 + $num2; break; case self::OP_SUB: $num = $num1 + $num2; break; case self::OP_MUL: $num = $num1 * $num2; break; case self::OP_DIV: $num = $num1 / $num2; break; default: break; } return $num; } } $cal_obj = new SimpleCalculator(); $a = $cal_obj->calculate("30+3-2+0.5*10/4+5"); var_dump($a); //41.25 $a = $cal_obj->calculate("30*2/3+0.5*10/4+5"); var_dump($a); //26.25
(6)二叉樹順序存儲轉鏈式存儲spa
Class BinaryTree { /** * 二叉樹順序存儲轉鏈式存儲 * @param $arr * 二叉樹順序存儲是按照徹底二叉樹來存的,徹底二叉樹節點i的左右子節點編號分別爲2i+1 2i+2,父節點編號爲(i-1)/2 * 本題要點在於怎麼記錄下節點對應的指針,過程當中有許多指針須要記錄,這裏採用了map來記錄(應該也能夠使用遞歸來解決這個問題) */ public function arr2Link($arr) { $len = count($arr); if ($len == 0) { return null; } $root = new BinaryTreeNode(); $root->val = $arr[0]; $node_map = array(0 => $root); //用於記錄全部node $i = 1; while ($i < $len) { if ($arr[$i] == null) { $par = floor(($i - 1) / 2); $par_node = $node_map[$par]; //不會出現$node_map[$par]不存在的狀況,出現這種狀況說明$arr有錯誤 $node = new BinaryTreeNode(); $node->val = $arr[$i]; if (2 * $par + 1 == $i) { $par_node->left = $node; } else { $par_node->right = $node; } $node_map[$i] = $node; } } return $root; } }
(7)二叉樹的廣度優先遍歷、深度優先遍歷指針
Class BinaryTree { public $visit_func = null; /** * 廣度優先遍歷 * @param $root */ public function broadOrder($root) { $queue = new Queue(); if ($root != null) { $queue->enqueue($root); } while (!$queue->isEmpty()) { $pointer = $queue->dequeue(); $this->visit_func($pointer); if ($pointer->left != null) { $queue->enqueue($pointer->left); } if ($pointer->right != null) { $queue->enqueue($pointer->right); } } } /** * 前序遍歷(遞歸) * @param $root */ public function preOrderR($root) { if ($root != null) { $this->visit_func($root); $this->preOrderR($root->left); $this->preOrderR($root->right); } } /** * 前序遍歷(非遞歸) * @param $root */ public function preOrderNR($root) { $stack = new Stack(); $pointer = $root; while ($pointer != null || !$stack.isEmpty()) { if ($pointer != null) { $this->visit_func($pointer); if ($pointer->right != null) { $stack->push($pointer->right); } $pointer = $pointer->left; } else { $pointer = $stack->pop(); } } } /** * 中序遍歷(遞歸) * @param $root */ public function inOrderR($root) { if ($root != null) { $this->preOrderR($root->left); $this->visit_func($root); $this->preOrderR($root->right); } } /** * 中序遍歷(非遞歸) * @param $root */ public function inOrderNR($root) { $stack = new Stack(); $pointer = $root; while ($pointer != null || !$stack.isEmpty()) { if ($pointer != null) { $stack->push($pointer); $pointer = $pointer->left; } else { $pointer = $stack->pop(); $this->visit_func($pointer); $pointer = $pointer->right; } } } }
(8)二叉搜索樹的插入code
Class BinarySearchTree { /** * 二叉搜索樹插入 * @param $root 此處認爲root不空 * @param $val */ public function insert($root, $val) { $pointer = $root; $prev = null; while ($pointer != null) { $prev = $pointer; if ($val == $pointer->val) { return false; } else if ($val < $pointer->val) { $pointer = $pointer->left; } else { $pointer = $pointer->right; } } $node = new BinarySearchNode($val); if ($val < $prev->val) { $prev->left = $node; } else { $prev->right = $node; } return true; } }