zoukankan      html  css  js  c++  java
  • 数据结构常见算法代码实现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;
        }
    }
  • 相关阅读:
    js的基本数据类型有哪些?
    页面优化的方式有哪些?
    为什么要用rem
    sass开发过程中遇到的几个坑
    js事件监听
    js数组去重的方法
    什么是怪异盒模型
    Cookie SameSite属性介绍及其在ASP.NET项目中的应用
    HttpServlet在第一个Servlet程序中的知识点
    Myeclipse 2017 创建第一个servlet步骤
  • 原文地址:https://www.cnblogs.com/livepeace/p/8227806.html
Copyright © 2011-2022 走看看