• 由PHP实现单向链表引发的对象赋值,对象传参,链表操作引发的一系列问题


    2019年2月25日14:21:13

    测试版本php 5.4 ,5.6,7.0,7.2

    代码请看: https://www.cnblogs.com/zx-admin/p/10373866.html

    1,对象赋值

    final class Node {
    
        public $data;
        public $next = null;
    
        public function __construct($data) {
            $this->data = $data;
        }
    
    }
    
    $a = new Node(['a']);
    p($a->data);
    $b = $a;
    //修改$a的data看是否影响
    $a->data = 'sssss';
    p($b->data);
    Array
    (
        [0] => a
    )
    sssss

    会影响$a的数据

    $b = &$a;
    $b = $a;

    对于对象来说就是取地址符,但是注意PHP的&不是取地址符,是别名,注意这个是官方解释,但是注意下面的 对象传参,又是另一种写法

    $b = clone $a;

    会裂变成连个完全独立的内存地址指向

    2,对象传参,或者对象传值,对象数据内部遍历指针的问题

    代码

    final class Node {
    
        public $data;
        public $next = null;
    
        public function __construct($data) {
            $this->data = $data;
        }
    
    }
    
    final class LinkedList {
    
    //    //从链表尾部压入一个节点,节点自动维护,不需要要像main方法那样自己维护
        public function push(Node $head, Node $Node) {
            $current = $head; //让$current指向$head;
            while ($current->next != null) {
                $current = $current->next;
            }
            $current->next = $Node->next;
            $current->next = $Node;
        }
    
        //从链表尾压出一个节点
        public function pop(Node $head) {
            $current = $head; //让$current指向$head;
            while ($current->next != null) {
                //提前查找链表尾部是否为空,为空就是尾部,吧当前节点的next复制问NULL,就是尾部元素干掉
                if ($current->next->next == null) {
                    break;
                }
                $current = $current->next;
            }
            $current->next = null;
        }
    
    }
    
    $head = new Node([]);
    $a = new Node(['a']);
    $b = new Node(['b']);
    $c = new Node(['c']);
    $d = new Node(['d']);
    
    $LinkedList = new LinkedList();
    $LinkedList->push($head, $a);
    $LinkedList->push($head, $b);
    $LinkedList->push($head, $c);
    $LinkedList->push($head, $d);
    $LinkedList->pop($head);
    pp($head);

    结果

    Node Object
    (
        [data] => Array
            (
            )
    
        [next] => Node Object
            (
                [data] => Array
                    (
                        [0] => a
                    )
    
                [next] => Node Object
                    (
                        [data] => Array
                            (
                                [0] => b
                            )
    
                        [next] => Node Object
                            (
                                [data] => Array
                                    (
                                        [0] => c
                                    )
    
                                [next] => 
                            )
    
                    )
    
            )
    
    )

    现阶段从结果反推的是对象传参,会自动变成引用对象传参,就是我们平常的写法

    function functionName(&$param) {
        
    }

    类似这种的效果

    但是,这个还不是关键

    这段代码才是关键

      public function push(Node $head, Node $Node) {
            $current = $head; //让$current指向$head;
            while ($current->next != null) {
                $current = $current->next;
            }
            $current->next = $Node->next;
            $current->next = $Node;
        }

    还可以写成这样的

        public function push(Node $head, Node $Node) {
    
            while ($head->next != null) {
                $head = $head->next;
            }
            $head->next = $Node->next;
            $head->next = $Node;
        }

    按照我们正常的理解,遍历一个对象  $head 被再次复制,那么遍历到最后$head->next = $Node;应该只剩一个对象元素才对

    但是打印 pp($head);依然是没有问题是一个完整的链表

    因为无法理解这个遍历过程  pop方法我写了两天无法完成,后来是通过画出链表结构才写出来的了,同时参考了

    https://blog.csdn.net/wenximalong/article/details/8296061 

    但是依然无法理解遍历对象的为什么不管有没有指向$head 的变量使用while遍历的时候发生了什么,这种结构的树状的对象数据,for或者foreach 当然不好使

    请参看

    https://www.cnblogs.com/zx-admin/p/9820866.html

    如果硬要解释的话,不管for foreach while  key next 等方法,在使用的时候都独立维护这一套指针,为了完成复杂的指针,指针移动完成不会影响传入的变量或者变量对象

    画了个示意图,不保证完全正确,不具备给他们语言的参考性,注意!

    就相当于while给你走指针,自己处理处理数据就可以,简单化了操作,复杂了理解,不确定是否理解正确,如果有问题请反馈

  • 相关阅读:
    两种常用图像识别迁移学习方法
    学习备忘
    图像处理代码举例(C++、MATLAB、OpenCV)
    Java 读取clob字段的几种方法
    Oracle 查询表注释以及字段注释
    Oracle 查询表的索引包含的字段
    Oracle 获取表的主键、外键以及唯一约束条件
    Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别
    Oracle 表结构、索引以及分区信息查询
    Java中的String,StringBuilder,StringBuffer三者的区别
  • 原文地址:https://www.cnblogs.com/zx-admin/p/10430782.html
Copyright © 2020-2023  润新知