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 相关文章推荐
图书管理程序(二)
Oct 09 PHP
PHP的中问验证码
Nov 25 PHP
纯真IP数据库的应用 IP地址转化成十进制
Jun 14 PHP
php smarty 二级分类代码和模版循环例子
Jun 01 PHP
PHP大小写问题:函数名和类名不区分,变量名区分
Jun 17 PHP
浅谈使用 PHP 进行手机 APP 开发(API 接口开发)
Aug 11 PHP
ThinkPHP文件上传实例教程
Aug 22 PHP
PHP类的封装与继承详解
Sep 29 PHP
php开发微信支付获取用户地址
Oct 04 PHP
php将数组存储为文本文件方法汇总
Oct 28 PHP
php实现点击可刷新验证码
Nov 07 PHP
Yii2创建表单(ActiveForm)方法详解
Jul 23 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
php恢复数组的key为数字序列的方法
2015/04/28 PHP
PHP 中魔术常量的实例详解
2017/10/26 PHP
PHP封装的简单连接MongoDB类示例
2019/02/13 PHP
PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
2019/02/20 PHP
javascript一些实用技巧小结
2011/03/18 Javascript
JQuery中判断一个元素下面是否有内容或者有某个标签的判断代码
2012/02/02 Javascript
jQuery使用ajaxSubmit()提交表单示例
2014/04/04 Javascript
分享一则javascript 调试技巧
2015/01/02 Javascript
JavaScript为事件句柄绑定监听函数实例详解
2015/12/15 Javascript
JavaScript继承模式粗探
2016/01/12 Javascript
js改变html的原有内容实现方法
2016/10/05 Javascript
如何判断出一个js对象是否一个dom对象
2016/11/24 Javascript
JS实现加载时锁定HTML页面元素的方法
2017/06/24 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
详解AngularJS跨页面传值(ui-router)
2017/08/23 Javascript
js实现小时钟效果
2020/03/25 Javascript
vue商城中商品“筛选器”功能的实现代码
2020/07/01 Javascript
vue v-model的用法解析
2020/10/19 Javascript
手写Vue2.0 数据劫持的示例
2021/03/04 Vue.js
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[38:31]完美世界DOTA2联赛PWL S3 Magma vs GXR 第一场 12.13
2020/12/17 DOTA
python使用Apriori算法进行关联性解析
2017/12/21 Python
python操作excel的方法(xlsxwriter包的使用)
2018/06/11 Python
使用CSS3的rem属性制作响应式页面布局的要点解析
2016/05/24 HTML / CSS
Html5导航栏吸顶方案原理与对比实现
2020/06/10 HTML / CSS
英国买鞋网站:Charles Clinkard
2019/11/14 全球购物
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
2014/05/20 面试题
物业工作计划书
2014/01/10 职场文书
旷课检讨书2000字
2014/01/14 职场文书
药剂专业求职信
2014/06/20 职场文书
土建施工员岗位职责
2014/07/16 职场文书
个人授权委托书格式
2014/08/30 职场文书
Golang 编译成DLL文件的操作
2021/05/06 Golang
SQL Server携程核心系统无感迁移到MySQL实战
2022/06/01 SQL Server
react中useState使用:如何实现在当前表格直接更改数据
2022/08/05 Javascript