利用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 相关文章推荐
兼容多浏览器的字幕特效Marquee的通用js类
Jul 20 Javascript
json数据的列循环示例
Sep 06 Javascript
jquery中的on方法使用介绍
Dec 29 Javascript
通用javascript代码判断版本号是否在版本范围之间
Nov 29 Javascript
jQuery实现鼠标选文字发新浪微博的方法
Apr 02 Javascript
jQuery实现可展开折叠的导航效果示例
Sep 12 Javascript
Node.js使用Express.Router的方法
Nov 14 Javascript
详解Vue2 SSR 缓存 Api 数据
Nov 20 Javascript
vue实现点击选中,其他的不选中方法
Sep 05 Javascript
JS实现十分钟倒计时代码实例
Oct 18 Javascript
vue.js的vue-cli脚手架中使用百度地图API的实例
Jan 21 Javascript
15分钟上手vue3.0(小结)
May 20 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中的Streams详细介绍
2014/11/12 PHP
Laravel框架Eloquent ORM删除数据操作示例
2019/12/03 PHP
JS分割字符串并放入数组的函数
2011/07/04 Javascript
关于Javascript与iframe的那些事儿
2013/07/04 Javascript
使用jquery hover事件实现表格的隔行换色功能示例
2013/09/03 Javascript
jquery fancybox ie6不显示关闭按钮的解决办法
2013/12/25 Javascript
基于javascript的COOkie的操作实现只能点一次
2014/12/26 Javascript
分析了一下JQuery中的extend方法实现原理
2015/02/27 Javascript
基于javascript实现简单计算器功能
2016/01/03 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
利用Query+bootstrap和js两种方式实现日期选择器
2017/01/10 Javascript
jQuery点击导航栏选中更换样式的实现代码
2017/01/23 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
javascript触发模拟鼠标点击事件
2019/06/26 Javascript
简述ES6新增关键字let与var的区别
2019/08/23 Javascript
vue element 中的table动态渲染实现(动态表头)
2019/11/21 Javascript
浅谈Vue 函数式组件的使用技巧
2020/06/16 Javascript
[50:02]完美世界DOTA2联赛PWL S2 Magma vs FTD 第三场 11.29
2020/12/03 DOTA
在Python程序中操作文件之isatty()方法的使用教程
2015/05/24 Python
基于python requests库中的代理实例讲解
2018/05/07 Python
详解用Python练习画个美队盾牌
2019/03/23 Python
python 实现在一张图中绘制一个小的子图方法
2019/07/07 Python
Python 占位符的使用方法详解
2019/07/10 Python
django的ORM操作 增加和查询
2019/07/26 Python
详解Python用三种方式统计词频的方法
2019/07/29 Python
Python3实现mysql连接和数据框的形成(实例代码)
2020/01/17 Python
python之MSE、MAE、RMSE的使用
2020/02/24 Python
使用jupyter Nodebook查看函数或方法的参数以及使用情况
2020/04/14 Python
Django执行源生mysql语句实现过程解析
2020/11/12 Python
独特的礼品和创新的科技产品:The Grommet
2018/02/24 全球购物
联想新西兰官方网站:Lenovo New Zealand
2018/10/30 全球购物
北欧最好的童装网上商店:Babyshop
2019/09/15 全球购物
公司建议书怎么写
2014/05/15 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
小学一年级语文教学反思
2016/03/03 职场文书
2019入党申请书范文3篇
2019/08/21 职场文书