PHP 實現遞迴刪除連結串列元素
阿新 • • 發佈:2020-12-12
PHP 實現遞迴刪除連結串列元素
這篇檔案介紹一下 遞迴
,遞迴的本質是將原來的問題轉化為更小的同一個問題,解決這些更小問題的過程。下面通過兩個遞迴的例子幫助學習對遞迴的理解。
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-poetry/data-structure
掃碼關注愛因詩賢