<?php
// 节点
class Node {
public $data = null;
public $next = null;
public function __construct($value = 0, $next = null) {
$this->data = $value;
$this->next = $next;
}
}
// 单链表
class LinkList {
public $head;// 头结点用于存储链表长度和指向后面结点
public function __construct() {
$this->head = new Node();
$this->head->data = 0;
}
// 批量创建新节点
public function CreateManyLinkList($size) {
//在当前链表后面创建多个
if ($size <= 0 ) {
throw new Exception("创建范围不合法");
}
$prev = $this->head;
// 处理之前已经有元素的链表
while ($prev->next != null ) {
$prev = $prev->next;//这样就一直移动到了最后一位
}
for ($i=1; $i <= $size; $i++) {
$prev->next = new Node(0, null);
$prev = $prev->next;
}
$this->head->data += $size;
}
public function ListInsert($index, $value) {
if ($index > $this->head->data || $index <= 0) {
throw new Exception("添加位置超出了链表范围");
}
$prev = $this->head;// 如果添加的位置为0就是这个 如果不为0 就是下面的循环
for ($i=1; $i < $index; $i++) {
$prev = $prev->next;
}
// 这里的$prev->next为原来的下一个节点 现在通过new添加了一个新的 而新的节点被赋值到了$prev->next变量中 换句话说就是替换了原来指向的数据,而原来节点的数据被新建的节点所使用 用来给自己的next属性赋值 相当于新的节点的next指向了原来$prev->next所指向的位置
$prev->next = new Node($value, $prev->next);
// 因为添加了新的节点 所以链表长度加1
$this->head->data++;
}
public function ListDelete($index) {
if ($index > $this->head->data || $index <= 0) {
throw new Exception("超出链表范围");
}
$prev = $this->head;
for ($i=1; $i <= $index; $i++) {
if ($i == $index) {
$q = $prev->next;
$prev->next = $q->next;
//$prev->next = $prev->next->next;
} else {
$prev = $prev->next;// 每一次迭代都要更新$prev的值为下一个元素的值
}
}
$this->head->data--;// 删除了之后对节点数量减一
}
public function ListEmpty() {
if ($this->head->data == 0) {
return true;
} else {
return false;
}
}
public function ClearList() {
$this->head->next = new Node();
$this->head->data = 0;
}
public function GetElem($index) {
if ($index > $this->head->data || $index <= 0) {
throw new Exception("超出链表范围");
}
$prev = $this->head->next;
for ($i=1; $i <= $index; $i++) {
if ($i == $index) {
return $prev->data;
} else {
$prev = $prev->next;// 一直向后迭代
}
}
}
public function LocateElem($value) {
$prev = $this->head->next;
while ($prev) {// 最后一个的next将为null
if ($prev->data == $value) {
return true;
} else {
$prev = $prev->next;
}
}
return false;
}
// 根据索引设置元素值
public function setElem($index, $value) {
if ($index > $this->head->data || $index <= 0) {
throw new Exception("超出链表范围");
}
$prev = $this->head->next;
for ($i=1; $i <= $index; $i++) {
if ($i == $index) {
$prev->data = $value;
} else {
$prev = $prev->next;
}
}
}
public function ListLenght() {
return $this->head->data;
}
}
$linkList = new LinkList();
$linkList->CreateManyLinkList(3);
$linkList->ListInsert(1,999);
$linkList->setElem(1,555);
$linkList->ListInsert(3,44);
$linkList->ListInsert(4,66);
$linkList->ListInsert(5,77);
var_dump($linkList->LocateElem(66));
var_dump($linkList->GetElem(5));
$linkList->ListDelete(5);
$linkList->setElem(6,999);
print_r($linkList);
// var_dump($linkList->ListLenght());
单向链表总结
优点
单向链表在确定元素位置时时间复杂度为O(n),确定后在添加和删除元素时的时间复杂度为O(1)
在内存中不必预先申请一整块内存,可以使用分散的内存进行存储
缺点
如果要查询元素,时间复杂度为O(n)