利用PHP实现递归删除链表元素的方法示例


Posted in Javascript onOctober 23, 2020

前言

这篇文章介绍一下 递归,递归的本质是将原来的问题转化为更小的同一个问题,解决这些更小问题的过程。下面通过两个递归的例子帮助学习对递归的理解。

1.递归数组求和

例如某个数组 $arr = [1,2,3,4,5,6,7,8,9,10]; 需要求和,通过实现递归函数对数组求和来帮助学习对递归的理解。

1.1 输出文件 output_recursion.php

<?php
require 'ArrayRecursion.php';
/**
 * 递归实现数组求和
 */
$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo ArrayRecursion::recursionSum($arr);

1.2 ArrayRecursion 类

这是一个实现数组递归求和的代码,其中 recursionSum() 是一个递归函数,相当于把求和过程转化为更小的求和,最终实现想要的结果:

<?php
/**
 * 使用递归对数组求和 方便对递归的理解
 * Class ArrayRecursion
 */
class ArrayRecursion
{
  public static function sum(array $arr) {
    return self::recursionSum($arr);
  }
  public static function recursionSum(array $arr, $i = 0) {
    if (count($arr) == $i) {
      return 0;
    }
    return $arr[$i] + self::recursionSum($arr, $i + 1);
  }
}

Tips:这个求和过程仅仅只是帮助学习递归思想,实际求和可以直接遍历数组。

2.递归删除链表某个元素

例如某个链表 10->9->8->99->7->99->6->5->99->4->3->2->1->null 需要删除其中值等于 99 的元素,可以通过实现递归来得到删除指定元素的效果。

2.1 输出文件 output_recursion.php

<?php
require 'LinkedList.php';
require 'LinkedListRecursion.php';
/**
 * 首先实例化一个链表,向链表中添加50个元素
 */
$linkedList = new LinkedList();
for ($i = 0; $i < 50; $i++) {
  if ($i % 7 == 0) {
    $linkedList->addFirst(99);
  } else {
    $linkedList->addFirst($i);
  }
}
echo $linkedList->toString();
/**打印链表中元素
 * 99->48->47->46->45->44->43->99->41->40->39->
 * 38->37->36->99->34->33->32->31->30->29->99->27->
 * 26->25->24->23->22->99->20->19->18->17->16->15->
 * 99->13->12->11->10->9->8->99->6->5->4->3->2->1->99->null
 */
//将链表对象传入一个能删除指定元素的方法,如 99
echo LinkedListRecursion::deleteElement($linkedList, 99)->toString();
/**打印
 * 48->47->46->45->44->43->41->40->
 * 39->38->37->36->34->33->32->31->
 * 30->29->27->26->25->24->23->22->
 * 20->19->18->17->16->15->13->12->
 * 11->10->9->8->6->5->4->3->2->1->null
 */

2.2 LinkedList & Node 链表类

这是一个链表类,可以使用 addFirst() 方法向链表头部添加元素,可使用 getHead() 获取链表 head 节点对象信息,可以使用 setHead() 改变 head,另外下面定义了一个链表节点类 Node:

<?php
/**
 * 链表的实现
 * Class LinkedList
 */
class LinkedList
{
  private $dummyHead;
  private $size;
  /**
   * 初始化链表 null->null
   * LinkedList constructor.
   */
  public function __construct() {
    $this->dummyHead = new Node(null, null);
    $this->size = 0;
  }
  /**
   * 获取链表大小
   * @return int
   */
  public function getSize(): int {
    return $this->size;
  }
  /**
   * 判断链表是否为空
   * @return bool
   */
  public function isEmpty(): bool {
    return $this->size == 0;
  }
  /**
   * 在链表的第 index 位置添加元素
   * @param int $index
   * @param $e
   */
  public function add(int $index, $e): void {
    if ($index < 0 || $index > $this->size) {
      echo "索引范围错误";
      exit;
    }
    $prve = $this->dummyHead;
    for ($i = 0; $i < $index; $i++) {
      $prve = $prve->next;
    }
    //将上插入位置的上一个位置的 next 节点指向插入节点,插入节点的 next 节点信息指向原上节点的 next 节点
    $prve->next = new Node($e, $prve->next);
    $this->size++;
  }
  /**
   * 向链表开头添加元素
   * @param $e
   */
  public function addFirst($e): void {
    $this->add(0, $e);
  }
  /**
   * 向链表末尾添加元素
   * @param $e
   */
  public function addLast($e): void {
    $this->add($this->size, $e);
  }
  /**
   * 获取链表第 index 位置元素
   * @param $index
   */
  public function get($index) {
    if ($index < 0 || $index > $this->size) {
      echo "索引范围错误";
      exit;
    }
    $node = $this->dummyHead;
    for ($i = 0; $i < $index + 1; $i++) {
      $node = $node->next;
    }
    return $node->e;
  }
  /**
   * 获取链表第一个元素
   * @return mixed
   */
  public function getFirst() {
    return $this->get(0);
  }
  /**
   * 获取链表最后一个元素
   * @return mixed
   */
  public function getLast() {
    return $this->get($this->size - 1);
  }
  /**
   * 修改链表中第 index 位置元素值
   * @param $index
   * @param $e
   */
  public function update($index, $e) {
    if ($index < 0 || $index > $this->size) {
      echo "索引范围错误";
      exit;
    }
    $node = $this->dummyHead;
    for ($i = 0; $i < $index + 1; $i++) {
      $node = $node->next;
    }
    $node->e = $e;
  }
  /**
   * 判断链表中是否存在某个元素
   * @param $e
   * @return bool
   */
  public function contains($e): bool {
    for ($node = $this->dummyHead->next; $node != null; $node = $node->next) {
      if ($node->e == $e) {
        return true;
      }
    }
    return true;
  }
  /**
   * 删除链表中第 index 位置元素
   * @param $index
   */
  public function remove($index) {
    if ($index < 0 || $index > $this->size) {
      echo "索引范围错误";
      exit;
    }
    if ($this->size == 0) {
      echo "链表已经是空";
      exit;
    }
    $prve = $this->dummyHead;
    for ($i = 0; $i < $index; $i++) {
      $prve = $prve->next;
    }
    $node = $prve->next;
    $prve->next = $node->next;
    $this->size--;
    return $node->e;
  }
  /**
   * 删除链表头元素
   */
  public function removeFirst() {
    return $this->remove(0);
  }
  /**
   * 删除链表末尾元素
   */
  public function removeLast() {
    return $this->remove($this->size - 1);
  }
  /**
   * 获取头结点信息
   * @return mixed
   */
  public function getHead() {
    return $this->dummyHead->next;
  }
  /**
   * 设置头
   * @param Node $head
   */
  public function setHead(Node $head) {
    $this->dummyHead->next = $head;
  }
  /**
   * 链表元素转化为字符串显示
   * @return string
   */
  public function toString(): string {
    $str = "";
    for ($node = $this->dummyHead->next; $node != null; $node = $node->next) {
      $str .= $node->e . "->";
    }
    return $str . "null";
  }
}
class Node
{
  public $e;//节点元素
  public $next; //下个节点信息
  /**
   * 构造函数 设置节点信息
   * Node constructor.
   * @param $e
   * @param $next
   */
  public function __construct($e, $next) {
    $this->e = $e;
    $this->next = $next;
  }
}

2.3 LinkedListRecursion 类

这个类定义了一个 deleteElement(LinkedList $linkedList, $val) 方法可以将传进的链表类中指定元素值的节点删除掉(实际是节点的 next 重新指向),recursionDelete($head, $val) 方法是一个递归函数,它能递归删除 head 中指定元素值等于 $val 的节点删除:

<?php
/**
 * 递归删除链表指定元素
 * Class LinkedListRecursion
 */
class LinkedListRecursion
{
  public static function deleteElement(LinkedList $linkedList, $val) {
    $linkedList->setHead(self::recursionDelete($linkedList->getHead(), $val));
    return $linkedList;
  }
  
   /**
   * 递归函数 递归删除链表元素
   * @param $head
   * @param $val
   * @return null
   */
  private static function recursionDelete($head, $val) {
    if ($head == null) {
      return null;
    } else {
      if ($head->e == $val) {
        return self::recursionDelete($head->next, $val);
      } else {
        $head->next = self::recursionDelete($head->next, $val);
        return $head;
      }
    }
  }
}

代码仓库 :https://gitee.com/love-for-po...

总结

到此这篇关于利用PHP实现递归删除链表元素的文章就介绍到这了,更多相关PHP递归删除链表元素内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript oop开发滑动(slide)菜单控件
Aug 25 Javascript
jQuery学习笔记 更改jQuery对象
Sep 19 Javascript
js解决弹窗问题实现班级跳转DIV示例
Jan 06 Javascript
手机平板等移动端适配跳转URL的js代码
Jan 25 Javascript
PHP使用方法重载实现动态创建属性的get和set方法
Nov 17 Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
Jan 28 Javascript
举例讲解AngularJS中的模块
Jun 17 Javascript
javascript仿百度输入框提示自动下拉补全
Jan 07 Javascript
完美实现js焦点轮播效果(二)(图片可滚动)
Mar 07 Javascript
jQuery实现的事件绑定功能基本示例
Oct 11 jQuery
使用Angular CLI从蓝本生成代码详解
Mar 24 Javascript
详解webpack4多入口、多页面项目构建案例
May 25 Javascript
如何在面试中手写出javascript节流和防抖函数
Oct 22 #Javascript
如何通过Proxy实现JSBridge模块化封装
Oct 22 #Javascript
微信小程序canvas动态时钟
Oct 22 #Javascript
vue-cli —— 如何局部修改Element样式
Oct 22 #Javascript
微信小程序入门之绘制时钟
Oct 22 #Javascript
微信小程序入门之指南针
Oct 22 #Javascript
微信小程序实现拼图小游戏
Oct 22 #Javascript
You might like
PHP 数据结构 算法描述 冒泡排序 bubble sort
2011/07/10 PHP
php图片加中文水印实现代码分享
2012/10/31 PHP
php实现简易聊天室应用代码
2015/09/23 PHP
Yii2实现跨mysql数据库关联查询排序功能代码
2017/02/10 PHP
js 事件小结 表格区别
2007/08/13 Javascript
jquery入门—访问DOM对象方法
2013/01/07 Javascript
给事件响应函数传参数的四种方式小结
2013/12/05 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
2015/10/16 Javascript
Javascript原型链的原理详解
2016/01/05 Javascript
Jquery判断form表单数据是否变化
2016/03/30 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
深入理解Javascript中的观察者模式
2017/02/20 Javascript
JS组件系列之MVVM组件 vue 30分钟搞定前端增删改查
2017/04/28 Javascript
原生JS实现的多个彩色小球跟随鼠标移动动画效果示例
2018/02/01 Javascript
JS实现数组删除指定元素功能示例
2019/06/05 Javascript
[53:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第一场 1月31日
2021/03/11 DOTA
python局部赋值的规则
2013/03/07 Python
Python文件右键找不到IDLE打开项解决办法
2015/06/08 Python
python 写入csv乱码问题解决方法
2016/10/23 Python
Python 转义字符详细介绍
2017/03/21 Python
Python基于identicon库创建类似Github上用的头像功能
2017/09/25 Python
详解Python开发中如何使用Hook技巧
2017/11/01 Python
详解django自定义中间件处理
2018/11/21 Python
python opencv 简单阈值算法的实现
2019/08/04 Python
python脚本监控logstash进程并邮件告警实例
2020/04/28 Python
html5实现多文件的上传示例代码
2014/02/13 HTML / CSS
屈臣氏俄罗斯在线商店:Watsons俄罗斯
2020/08/03 全球购物
介绍一下mysql的日期和时间函数
2013/03/28 面试题
小学岗位竞聘方案
2014/01/22 职场文书
业务员的岗位职责
2014/03/15 职场文书
乡镇纠风工作实施方案
2014/03/22 职场文书
网络技术专业求职信
2014/05/02 职场文书
实习工作表现评语
2014/12/31 职场文书
成绩单评语
2015/01/04 职场文书
酒店优秀员工推荐信
2015/03/24 职场文书
2016年过年放假安排通知
2015/08/18 职场文书