利用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代码
Oct 09 Javascript
Javascript与vbscript数据共享
Jan 09 Javascript
几个高效,简洁的字符处理函数
Apr 12 Javascript
跟我学习javascript的var预解析与函数声明提升
Nov 16 Javascript
Javascript实现图片不间断滚动的代码
Jun 22 Javascript
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
May 25 Javascript
JS实现移动端按首字母检索城市列表附源码下载
Jul 05 Javascript
vue上传图片组件编写代码
Jul 26 Javascript
深入理解Angularjs 脏值检测
Oct 12 Javascript
JS实现的全选、全不选及反选功能【案例】
Feb 19 Javascript
微信小程序把百度地图坐标转换成腾讯地图坐标过程详解
Jul 10 Javascript
80行代码写一个Webpack插件并发布到npm
May 24 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一些有意思的小区别
2006/12/06 PHP
php支付宝手机网页支付类实例
2015/03/04 PHP
浅谈PHP中try{}catch{}的使用方法
2016/12/09 PHP
详解PHP素材图片上传、下载功能
2019/04/12 PHP
Laravel如何创建服务器提供者实例代码
2019/04/15 PHP
jQuery 方法大全方便学习参考
2010/02/25 Javascript
JavaScript实现数字数组按照倒序排列的方法
2015/04/06 Javascript
jfreechart插件将数据展示成饼状图、柱状图和折线图
2015/04/13 Javascript
jQuery满意度星级评价插件特效代码分享
2015/08/19 Javascript
canvas 实现中国象棋
2017/02/17 Javascript
详解Vue 动态添加模板的几种方法
2017/04/25 Javascript
JS触摸与手势事件详解
2017/05/09 Javascript
vue中计算属性(computed)、methods和watched之间的区别
2017/07/27 Javascript
10分钟上手vue-cli 3.0 入门介绍
2018/04/04 Javascript
React中的render何时执行过程
2018/04/13 Javascript
详解vue-cli 3.0 build包太大导致首屏过长的解决方案
2018/11/10 Javascript
js中位运算的运用实例分析
2018/12/11 Javascript
jQuery实现的3D版图片轮播示例【滑动轮播】
2019/01/18 jQuery
解决node终端下运行js文件不支持ES6语法
2020/04/04 Javascript
微信小程序开发(二):页面跳转并传参操作示例
2020/06/01 Javascript
Python字符和字符值(ASCII或Unicode码值)转换方法
2015/05/21 Python
Fabric 应用案例
2016/08/28 Python
Python异步操作MySQL示例【使用aiomysql】
2019/05/16 Python
python爬虫之遍历单个域名
2019/11/20 Python
基于keras中的回调函数用法说明
2020/06/17 Python
HTML5 新旧语法标记对我们有什么好处
2012/12/13 HTML / CSS
法国二手MacBook销售网站:Okamac
2019/03/18 全球购物
Regatta官网:英国最受欢迎的户外服装和鞋类品牌
2019/05/01 全球购物
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
做一个有道德的人活动实施方案
2014/08/23 职场文书
缓刑期间思想汇报范文
2014/10/10 职场文书
2014年人民警察入党思想汇报
2014/10/12 职场文书
机动车交通事故协议书
2015/01/29 职场文书
大学考试作弊检讨书
2015/05/06 职场文书
初中英语教学反思范文
2016/02/15 职场文书
python中redis包操作数据库的教程
2022/04/19 Python