(思维进阶)一、进阶知识梳理一+算法(tree)

2018-10-14 09:42:00 995 思小齐 思小齐

前言
php7特性,面向对象、提高算法等。
感觉学习进入平台期,个人的一些理解梳理。

大神镇楼:
大神:鸟哥 [风雪之隅][1]
大神:韩天峰 [rango][2]

1.php部分

a.php7对php5新特性

(1).null合并运算符(??)
$param = $_GET['param'] ?? 1;//1
(2).define() 定义常量数组
(3).组合比较符(<=>)
echo "a" <=> "a"; // 0 => 成立顺序对应-1.0.1
(4).变量类型声明两种模式: 强制(默认)和严格模式
declare(strict_types=1);//值为1代表为严格校验的模式
(5).返回值类型声明
(6).PHP7 错误处理
PHP7 改变了大多数错误的报告方式,现在大多数错误被作为 Error 异常抛出。这种 Error 异常可以像普通异常一样被 try / catch 块所捕获。
(7)打开配置项的opcache,php7.3.6默认:

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.enable_cli=1

b.面向对象编程

参考laravel学院《现代PHP/新特性

(1).善用接口(定义处extends),分离实现细节;
(2).使用trait(特性:内部use),追加属性、方法;
(3).闭包的调用,调试;
(4).迭代Iterator/yield使用。

c.实用算法相关

(1).循环调用=>预约变现:使用生成器(yield)

function makeRange($length) {
    for ($i=0; $i<$length; $i++) {
        yield $i;
    }
}
foreach (makeRange(1000000) as $i) {
    echo $i . PHP_EOL;
}

yield让步,主动让出cpu执行权限,无法取回,等待next主动调用,参考《PHP yield 分析,以及协程的实现,超详细版(上)》。
(2).迭代树循环=>提纲挈领:使用&地址引用

function genTree(array $items,string $id='gcid',string $pid='parentgcid',string $son='children') array {
    $tree = array(); //格式化的树
    $tmpMap = array();  //临时扁平数据
    //全部加载到内存,不用迭代器
    foreach ($items as $item) {
        $tmpMap[$item[$id]] = $item;
    }
    foreach ($items as $item) {
        if (isset($tmpMap[$item[$pid]])) {
            //把父子结构转换引用成地址,准备据完成后,输出时即是所需数据
            $tmpMap[$item[$pid]][$son][] = &$tmpMap[$item[$id]];
        } else {
            $tree[] = &$tmpMap[$item[$id]];
        }
    }
    return $tree;
}

2.概念原理部分

a.epool进程(linux)I/O复用

[nginx运行模型]

epoll提供了三个函数,epoll_create,epoll_ctl和epoll_wait,epoll_create是创建一个epoll句柄;epoll_ctl是注册要监听的事件类型;epoll_wait则是等待事件的产生。
I/O多路复用就是通过一种机制,一个进程可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

b.Raft分布式一致性协议

[redis集群使用]

借鉴了美国总统大选的策略,采用精英领导全局的方案,整个集群中只有 Leader 可以处理 client 发送过来的请求,其他非 Leader 节点即使接收到请求也必须将其转发到 Leader 节点进行处理。集群中的成员分三种角色:Leader、Follower、Condidate候选人。
选举过程:集群初始状态下是没有 Leader 的, 集群中所有成员均是 Follower,在选举开始期间所有 Follower 均可参与选举、角色转变为 Condidate, Leader 由集群中所有的 Condidate 投票选出,最后获得投票最多的 Condidate 获胜,角色转变为 Leader,其余角色转变为 Follower 开始服从 Leader 领导。
选不出 Leader 时:引入了北洋时期袁世凯获选大总统的谋略,即选不出 Leader 不罢休,直到选出为止。一轮选不出 Leader,便令所有 Condidate 随机 sleep重新投票。

c.php关键字self与static

static 是$this 的升级版。($this指定的变化的对象,static 指定的是变化的类),这里注意对象和类的区别。

class P
{
    public static function getChild() {
        return static::class. '/'. self::class. '|'. __CLASS__;
    }
    public function get() {
        return static::class. '<'. self::class. '|'. __CLASS__;
    }
} 

class C extends P {} 
echo C::getChild(), PHP_EOL; //类调用,输出:C/P|P

$c = new C(); //对象调用
echo $c->get(). PHP_EOL; //输出:C<P|P

d.面向对象的“绕人”链表

参考《链表数据结构》,写完自己看不懂:

// 英雄类
class Hero{
    public $data;
    public $next=null;
    public function __construct($no=0,$name='',$nickname=''){
        $data['no'] = $no;
        $data['name'] = $name;
        $data['nickname'] = $nickname;
        $this->data = $data;
    }
}
$head=new Hero();

$hero1=new Hero(1,"宋江","及时雨");
$head->next=$hero1;

$hero2=new Hero(8,"卢俊义","玉麒麟");
$hero1->next=$hero2;
function print_list($cur){
    while($cur->next!=null){
        echo "姓名:".$cur->next->data['no'].'. '.$cur->next->data['name']."<br/>";
        $cur=$cur->next;
    }
    echo '**********************************<br/>';
}
echo '<pre>';

//批量添加,链式传递&
function insert_list($node, ... $args)
{
    foreach($args as $data){
        $next = new Hero($data[0], $data[1], $data[2]);
        $node->next = $next;
        $node = $next; //注意迭代
    }
}
print_list($hero2);
insert_list($hero2, [13,'赵小白','小白'], [6,'李兴河','小何'], [11,'张大河','大何']);
print_list($hero1);
print_list($head);

//排序,返回新序列
function sort_list($node, $order_field='no', $order_type="ASC"){
    $list2array=[];
    $node2 = $node;
    while($node2->next != null){
        $list2array[$node2->next->data[$order_field]] = [
            $node2->next->data['no'],
            $node2->next->data['name'],
            $node2->next->data['nickname']
        ];
        $node2 = $node2->next;
    }
    if( $order_type=="ASC"){
        ksort($list2array);
    }else{
        krsort($list2array);
    }
    $head_node = new Hero();//写时复制
    function insertls($node, $list2array) {
        foreach($list2array as $data){
            $next = new Hero($data[0], $data[1], $data[2]);
            $node->next = $next;
            $node = $next; //注意迭代
        }
    }
    insertls($head_node, $list2array);

    return $head_node;
}
$new_head = sort_list($head);

print_list($new_head);

上面提到迭代,使用Iterator试下:

Iterator::current — 返回当前元素 3
Iterator::key — 返回当前元素的键 4
Iterator::next — 向前移动到下一个元素 1.1
Iterator::rewind — 返回到迭代器的第一个元素 1.0
Iterator::valid — 检查当前位置是否有效 2

查完资料,放弃。