PHP双向链表定义与用法示例


Posted in PHP onJanuary 31, 2018

本文实例讲述了PHP双向链表定义与用法。分享给大家供大家参考,具体如下:

由于需要对一组数据多次进行移动操作,所以写个双向链表。但对php实在不熟悉,虽然测试各个方法没啥问题,就是不知道php语言深层的这些指针和unset有什么注意的地方,贴出来让大家教育吧。效率没测试....求谅解~

<?php
/**
 * **双向链表
 * @author zhiyuan12@
 */
/**
 * 链表元素结点类
 */
class Node_Element {
  public $pre = NULL; // 前驱
  public $next = NULL; // 后继
  public $key = NULL; // 元素键值
  public $data = NULL; // 结点值
  function __Construct($key, $data) {
    $this->key = $key;
    $this->data = $data;
  }
}
/**
 * 双向链表类
 */
class DoubleLinkedList {
  private $head; // 头指针
  private $tail; // 尾指针
  private $current; // 当前指针
  private $len; // 链表长度
  function __Construct() {
    $this->head = self::_getNode ( null, null );
    $this->curelement = $this->head;
    $this->tail = $this->head;
    $len = 0;
  }
  /**
   * @ desc: 读取链表全部结点
   */
  public function readAll() {
    $tmp = $this->head;
    while ( $tmp->next !== null ) {
      $tmp = $tmp->next;
      var_dump ( $tmp->key, $tmp->data );
    }
  }
  public function move($pos1, $pos2) {
    $pos1Node = $this->findPosition ( $pos1 );
    $pos2Node = $this->findPosition ( $pos2 );
    if ($pos1Node !== null && $pos2Node !== null) {
      $tmpKey = $pos1Node->key;
      $tmpData = $pos1Node->data;
      $pos1Node->key = $pos2Node->key;
      $pos1Node->data = $pos2Node->data;
      $pos2Node->key = $tmpKey;
      $pos2Node->data = $tmpData;
      return true;
    }
    return false;
  }
  /**
   * @ desc: 在指定关键词删除结点
   *
   * @param : $key
   *     指定位置的链表元素key
   */
  public function delete($key) {
    $pos = $this->find ( $key );
    if ($pos !== null) {
      $tmp = $pos;
      $last = null;
      $first = true;
      while ( $tmp->next !== null && $tmp->next->key === $key ) {
        $tmp = $tmp->next;
        if (! $first) {
          $this->delNode ( $last );
        } else {
          $first = false;
        }
        $last = $tmp;
      }
      if ($tmp->next !== null) {
        $pos->pre->next = $tmp->next;
        $tmp->next->pre = $pos->pre;
      } else {
        $pos->pre->next = null;
      }
      $this->delNode ( $pos );
      $this->delNode ( $tmp );
    }
  }
  /**
   * @ desc: 在指定位置删除结点
   *
   * @param : $key
   *     指定位置的链表元素key
   */
  public function deletePosition($pos) {
    $tmp = $this->findPosition ( $pos );
    if ($tmp === null) {
      return true;
    }
    if ($tmp === $this->getTail ()) {
      $tmp->pre->next = null;
      $this->delNode ( $tmp );
      return true;
    }
    $tmp->pre->next = $tmp->next;
    $tmp->next->pre = $tmp->pre;
    $this->delNode ( $tmp );
  }
  /**
   * @ desc: 在指定键值之前插入结点
   *
   * @param : $key
   *     //指定位置的链表元素key
   * @param : $data
   *     //要插入的链表元素数据
   * @param : $flag
   *     //是否顺序查找位置进行插入
   */
  public function insert($key, $data, $flag = true) {
    $newNode = self::_getNode ( $key, $data );
    $tmp = $this->find ( $key, $flag );
    if ($tmp !== null) {
      $newNode->pre = $tmp->pre;
      $newNode->next = $tmp;
      $tmp->pre = $newNode;
      $newNode->pre->next = $newNode;
    } else {
      $newNode->pre = $this->tail;
      $this->tail->next = $newNode;
      $this->tail = $newNode;
    }
    $this->len ++;
  }
  /**
   * @ desc: 在指定位置之前插入结点
   *
   * @param : $pos
   *     指定插入链表的位置
   * @param : $key
   *     指定位置的链表元素key
   * @param : $data
   *     要插入的链表元素数据
   */
  public function insertPosition($pos, $key, $data) {
    $newNode = self::_getNode ( $key, $data );
    $tmp = $this->findPosition ( $pos );
    if ($tmp !== null) {
      $newNode->pre = $tmp->pre;
      $newNode->next = $tmp;
      $tmp->pre = $newNode;
      $newNode->pre->next = $newNode;
    } else {
      $newNode->pre = $this->tail;
      $this->tail->next = $newNode;
      $this->tail = $newNode;
    }
    $this->len ++;
    return true;
  }
  /**
   * @ desc: 根据key值查询指定位置数据
   *
   * @param : $key
   *     //指定位置的链表元素key
   * @param : $flag
   *     //是否顺序查找
   */
  public function find($key, $flag = true) {
    if ($flag) {
      $tmp = $this->head;
      while ( $tmp->next !== null ) {
        $tmp = $tmp->next;
        if ($tmp->key === $key) {
          return $tmp;
        }
      }
    } else {
      $tmp = $this->getTail ();
      while ( $tmp->pre !== null ) {
        if ($tmp->key === $key) {
          return $tmp;
        }
        $tmp = $tmp->pre;
      }
    }
    return null;
  }
  /**
   * @ desc: 根据位置查询指定位置数据
   *
   * @param : $pos
   *     //指定位置的链表元素key
   */
  public function findPosition($pos) {
    if ($pos <= 0 || $pos > $this->len)
      return null;
    if ($pos < ($this->len / 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->len - $pos + 1;
      $count = 1;
      while ( $tmp->pre !== null ) {
        if ($count === $pos) {
          return $tmp;
        }
        $tmp = $tmp->pre;
        $count ++;
      }
    }
    return null;
  }
  /**
   * @ desc: 返回链表头节点
   */
  public function getHead() {
    return $this->head->next;
  }
  /**
   * @ desc: 返回链表尾节点
   */
  public function getTail() {
    return $this->tail;
  }
  /**
   * @ desc: 查询链表节点个数
   */
  public function getLength() {
    return $this->len;
  }
  private static function _getNode($key, $data) {
    $newNode = new Node_Element ( $key, $data );
    if ($newNode === null) {
      echo "new node fail!";
    }
    return $newNode;
  }
  private function delNode($node) {
    unset ( $node );
    $this->len --;
  }
}
$myList = new DoubleLinkedList ();
$myList->insert ( 1, "test1" );
$myList->insert ( 2, "test2" );
$myList->insert ( "2b", "test2-b" );
$myList->insert ( 2, "test2-c" );
$myList->insert ( 3, "test3" );
$myList->insertPosition ( 5, "t", "testt" );
$myList->readAll ();
echo "+++";
$myList->deletePosition(0);
$myList->readAll ();
echo "..." . $myList->getLength ();
var_dump ( $myList->findPosition ( 3 )->data );
?>

运行结果:

int(1)
string(5) "test1"
int(2)
string(7) "test2-c"
int(2)
string(5) "test2"
string(2) "2b"
string(7) "test2-b"
string(1) "t"
string(5) "testt"
int(3)
string(5) "test3"
+++int(1)
string(5) "test1"
int(2)
string(7) "test2-c"
int(2)
string(5) "test2"
string(2) "2b"
string(7) "test2-b"
string(1) "t"
string(5) "testt"
int(3)
string(5) "test3"
...6string(5) "test2"

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
[原创]效率较高的php下读取文本文件的代码
Jul 02 PHP
php auth_http类库进行身份效验
Mar 19 PHP
PHP 函数执行效率的小比较
Oct 17 PHP
paypal即时到账php实现代码
Nov 28 PHP
php中通过Ajax如何实现异步文件上传的代码实例
May 07 PHP
php的一个简单加密解密代码
Jan 14 PHP
yii实现CheckBox复选框在同一行显示的方法
Dec 03 PHP
php遍历目录方法小结
Mar 10 PHP
php实现仿写CodeIgniter的购物车类
Jul 29 PHP
PHP的时间戳与具体时间转化的简单实现
Jun 13 PHP
PHP超低内存遍历目录文件和读取超大文件的方法
May 01 PHP
在Laravel的Model层做数据缓存的实现
Sep 26 PHP
基于PHP实现的多元线性回归模拟曲线算法
Jan 30 #PHP
PHP 记录访客的浏览信息方法
Jan 29 #PHP
laravel ORM 只开启created_at的几种方法总结
Jan 29 #PHP
PHP+Redis 消息队列 实现高并发下注册人数统计的实例
Jan 29 #PHP
PHP 使用二进制保存用户状态的实例
Jan 29 #PHP
thinkphp3.2.0 setInc方法 源码全面解析
Jan 29 #PHP
Ubuntu上安装yaf扩展的方法
Jan 29 #PHP
You might like
咖啡知识 咖啡养豆要养多久 排气又是什么
2021/03/06 新手入门
PHP 创建文件(文件夹)以及目录操作代码
2010/03/04 PHP
js的onload事件及初始化按钮事件示例代码
2013/09/25 Javascript
jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮
2013/10/11 Javascript
jquery 根据name名获取元素的value值
2015/02/27 Javascript
理解javascript函数式编程中的闭包(closure)
2016/03/08 Javascript
JavaScript实现翻页功能(附效果图)
2017/02/16 Javascript
Node.JS中事件轮询(Event Loop)的解析
2017/02/25 Javascript
JS按钮闪烁功能的实现代码
2017/07/21 Javascript
基于wordpress的ajax写法详解
2018/01/02 Javascript
使用Node.js写一个代码生成器的方法步骤
2019/05/10 Javascript
如何在项目中使用log4.js的方法步骤
2019/07/16 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
D3.js 实现带伸缩时间轴拓扑图的示例代码
2020/01/20 Javascript
javascript 设计模式之组合模式原理与应用详解
2020/04/08 Javascript
微信小程序实现分页加载效果
2020/11/19 Javascript
python中查找excel某一列的重复数据 剔除之后打印
2013/02/10 Python
Python实现二叉堆
2016/02/03 Python
Python使用poplib模块和smtplib模块收发电子邮件的教程
2016/07/02 Python
Python常见读写文件操作实例总结【文本、json、csv、pdf等】
2019/04/15 Python
python的内存管理和垃圾回收机制详解
2019/05/18 Python
tensorflow 实现自定义梯度反向传播代码
2020/02/10 Python
pycharm中选中一个单词替换所有重复单词的实现方法
2020/11/17 Python
阿里旅行:飞猪
2017/01/05 全球购物
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
递归计算如下递归函数的值(斐波拉契)
2012/02/04 面试题
海量信息软件测试笔试题
2015/08/08 面试题
营销与策划应届生求职信
2013/11/04 职场文书
2015年幼儿园毕业感言
2014/02/12 职场文书
个人培训自我鉴定
2014/03/28 职场文书
写得不错的求职信范文
2014/07/11 职场文书
2014年党员学习“三严三实”思想汇报
2014/09/15 职场文书
音乐教师个人工作总结
2015/02/06 职场文书
后勤个人工作总结
2015/02/28 职场文书
Mysql - 常用函数 每天积极向上
2021/04/05 MySQL