「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」
链表是一个十分简单的数据结构,它的应用也比较广泛。
今天说一下在PHP中的使用对象实现单链表。
单链表实现
我们都知道链表中的每一个节点都是记录了两个信息,当前节点的元素数据和下一个节点的地址。串联起来就形成了链表。
那么使用对象如何实现呢?如何把每个节点连接起来呢?
节点类
首先我们创建一个节点类,包含节点所需的两个属性。每需要新增一个节点时,就创建一个节点类的对象,并初始化元素数据和下个节点地址。
链表类
通过调用 getData 方法就可以得到一个链表。根据下图我们详细说明一下。
链表的头部的元素数据一般都是 null,因此第25行代码创建一个空节点作为头节点。$this->listHead可以调用节点类的元素数据 $this->listHead->element和下个节点地址$this->listHead->next这两个属性使用。
然后把头节点地址赋值给一个变量 $prevNode,表示待插入节点的上一个节点。
遍历需要插入链表的数据,首先要新创建一个节点,即第29行代码,和创建头节点一样,只不过此节点的元素数据是有值的。创建好的节点怎样和其他节点相连呢?那就是把当前节点赋值给上一个节点的next的属性,上一个节点就是头节点,而头节点赋值给变量 $prevNode,相当于next的属性内存储了当前节点的对象数据。
然后再把当前节点赋值给变量 $prevNode,当前节点的next的属性,需要记录下次遍历的节点的对象,使其连接起来。
我们看到最后返回的是$this->listHead属性,但是上面把这个属性赋值给变量 $prevNode后,就没有使用了。这是怎么回事呢?
赋值操作会使两个变量互不相关,但是对象赋值,却是引用。由于我们每次增加新节点都是重新创建的节点对象,所以每次返回的都是不同的节点对象。所以每次为上一个节点的next的属性赋值后,就已经把所有节点连接了起来。
通过下面这张图,会看的直观一点。
上图中后面的数字,就是每次创建节点对象,每个数字表示不同的节点对象。
循环链表
循环链表就是链表的最后一个节点指向头节点的位置。
还是刚才创建单链表的代码,我们把图中注释的代码打开,就变成了一个循环链表。
上面实现的是首尾相连的链表,还有一种链表是中间循环,例如这种
这种循环链表在插入最后一个节点时,把地址指向了链表中间的任意节点。