用PHP实现双向链表,在实现上,与C++的区别,主要在指针与this的使用上的不同。在数据结构方面双向链表要考虑两个方向四个指向,每次增减节点时注意每个指向都要照顾到。
实现文件DoubleLinkList.php
<?php
/**
* **双向链表
* @author tju_zyt@tju.edu.cn
*
*/
/**
* 链表元素结点类
*/
class Node{
public $prev = NULL; // 前驱
public $next = NULL; // 后继
public $key = NULL; // 元素键值
public $data = NULL; // 结点值
function __Construct($key, $data) {
$this->key = $key;
$this->data = $data;
}
}
class DoubleLinkList{
private $head;
private $tail;
private $current;
private $size;
function __Construct(){
$this->head = $this->tail = NULL;
$this->size = 0;
}
/**
* 在链表头部加入节点
* @param $key 要插入元素的key
* @param $data 要插入链表元素的数据
*/
public function addFirst($key, $data){
$newNode = new Node($key, $data);
$newNode->next = $this->head;
$this->head->prev->next = $newNode;
$this->head->prev = $newNode;
$this->head = $newNode;
$this->size++;
if($this->tail === NULL){
$this->tail = $this->head;
}
}
/**
* 在链表尾部加入节点
* @param $key 要插入元素的key
* @param $data 要插入链表元素的数据
*/
public function addLast($key, $data){
if($this->tail === NULL){
$this->addFirst($key, $data);
}else{
$newNode = new Node($key, $data);
$newNode->prev = $this->tail;
$this->tail->next->prev = $newNode;
$this->tail->next = $newNode;
$this->tail = $newNode;
}
$this->size++;
}
/**
* 删除链表头部节点
*/
public function removeFirst(){
if($this->size == 0){
throw new Exception("The list is empty");
} else {
$tmp = $this->head;
$this->head = $tmp->next;
$this->head->prev = $tmp->prev;
if($this->head === NULL) $this->tail = NULL;
unset($tmp);
$this->size--;
}
}
/**
* 删除链表尾部节点
*/
public function removeLast(){
if($this->size == 0){
throw new Exception("The list is empty");
} else {
$tmp = $this->tail;
$this->tail = $tmp->prev;
$this->tail->next = $tmp->next;
if($this->tail === NULL) $this->head = NULL;
unset($tmp);
$this->size--;
}
}
/**
* 获得头部节点的数据
* @throws 链表为空
*/
public function getFirst(){
if($this->size == 0){
throw new Exception("The list is empty");
} else {
var_dump($this->head->key, $this->head->data);
}
}
/**
* 获得尾部节点的数据
* @throws 链表为空
*/
public function getLast(){
if($this->size == 0){
throw new Exception("The list is empty");
} else {
var_dump($this->tail->key, $this->tail->data);
}
}
/**
* 在指定位置插入节点
* @param $pos 指定元素在列表的位置
* @param $key 要插入元素的key
* @param $data 要插入链表元素的数据
*/
public function add($pos, $key, $data){
if($pos == 0){
$this->addFirst($key, $data);
}else if($pos >= $this->size){
$this->addLast($key, $data);
}else{
$this->current = $this->head;
for($i = 1; $i < $pos; $i++){
$this->current = $this->current->next;
}
$tmp = $this->current->next;
$newNode = new Node($key, $data);
$newNode->next = $tmp;
$newNode->prev = $this->current;
$this->current->next = $newNode;
$tmp->prev = $newNode;
$this->size++;
}
}
/**
* 在指定位置删除节点
* @param $pos 指定元素在列表的位置
* @param $key 要插入元素的key
* @param $data 要插入链表元素的数据
*/
public function remove($pos){
if($pos == 0){
$this->removeFirst();
}else if($pos >= $this->size){
$this->removeLast();
}else{
$this->current = $this->head;
for($i = 1; $i < $pos; $i++){
$this->current = $this->current->next;
}
$tmp = $this->current->next;
$this->current->next = $tmp->next;
$tmp->next->prev = $this->current;
$this->size--;
}
}
/**
* 获得所有节点的数据
* @throws 链表为空
*/
public function getAll(){
if($this->size == 0){
throw Exception("The list is empty");
} else {
$tmp = $this->head;
while($tmp !== NULL){
var_dump($tmp->key, $tmp->data);
$tmp = $tmp->next;
}
}
}
/**
* 根据key获得指定节点的数据
* @param $key 指定的key值
* @return $data 对应的数据
*/
public function findByKey($key){
$tmp = $this->head;
while ($tmp !== NULL) {
if ($tmp->key === $key) {
return $tmp->data;
}
$tmp = $tmp->next;
}
return null;
}
/**
* 根据pos获得指定节点的数据
* @param $pos 指定的key值
* @return $tmp 对应的key和data数据
*/
public function findByPos($pos){
if ($pos <= 0 || $pos > $this->size)
return null;
if ($pos < ($this->size / 2 + 1)) {
$tmp = $this->head;
$count = 0;
while ( $tmp->next !== null ) {
$tmp = $tmp->next;
$count++;
if ($count === $pos) {
return $tmp;
}
}
} else {
$tmp = $this->tail;
$pos = $this->size - $pos + 1;
$count = 1;
while ( $tmp->prev !== null ) {
if ($count === $pos) {
return $tmp;
}
$tmp = $tmp->pre;
$count++;
}
}
return null;
}
/**
* 清空链表
*/
public function clear(){
while($this->head !== NULL){
$tmp = $this->head;
$this->head = $this->head->next;
unset($tmp);
}
}
}
测试文件
<?php
include "./DoubleLinkList.php";
$list = new DoubleLinkList();
$list->addFirst(1, "orange");
$list->addLast(2, "apple");
$list->addLast(3, "banana");
$list->addFirst(4, "grape");
$list->getFirst();
$list->removeFirst();
$list->getLast();
echo "-----------------";
$list->getAll();
echo "-----------------";
$list->removeLast();
$list->getAll();
echo "-----------------";
$list->add(1, 4, "peal");
$list->getAll();
echo "-----------------";
$list->add(1, 5, "watermoon");
$list->addFirst(6, "strawberry");
$list->remove(3);
$list->getAll();
echo "-----------------";
var_dump($list->findByKey(2));
echo "-----------------";
$a = $list->findByPos(2);
var_dump($a->key, $a->data);
echo "-----------------";
$list->clear();
$list->getAll();