数据结构常见算法代码实现2-PHP

(4)朴素字符串匹配

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)不带括号的四则运算器

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)二叉树顺序存储转链式存储

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)二叉搜索树的插入

 

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;
    }
}

 

posted @ 2018-01-08 14:48  爱读书的小明  阅读(118)  评论(0编辑  收藏  举报