早上好,最近在看但鏈表的翻轉,之前一直困惑,怎樣使用php實現,後來發現重要的是捋清單鏈表的數據結構和翻轉的基本原理,至於什麼語言實現,萬變不離其中,都是一樣的道理,接下來,介紹一下,php實現單鏈表的翻轉。
1、最重要的是理解單鏈表的數據結構,(鏈表操作一定要畫圖,畫圖才能理解的更爲深刻。)
1:單向鏈表:
單向鏈表的鏈表對象維護了一個 first 引用,該引用指向節點鏈表中的第一個節點對象,每個節點對象維護一個 next 引用,next引用指向下一個節點對象;(這裏注意:是引用指向的是節點對象:節點對象包含存儲的數據和next引用)
2、我們知道迭代是從前往後依次處理,直到循環到鏈尾;而遞歸恰恰相反,首先一直迭代到鏈尾也就是遞歸基判斷的準則,然後再逐層返回處理到開頭。總結來說,鏈表翻轉操作的順序對於迭代來說是從鏈頭往鏈尾,而對於遞歸是從鏈尾往鏈頭。下面我會用詳細的圖文來剖析其中實現的細節
1)非遞歸方式(迭代)方式
迭代的方式是從鏈頭開始處理,如下圖給定一個存放5個數的鏈表
、
首先對於鏈表設置兩個指針:
然後依次將舊鏈表上每一項添加在新鏈表的後面,然後新鏈表的頭指針NewH移向新的鏈表頭,如下圖所示。此處需要注意,不可以上來立即將上圖中P->next直接指向NewH,這樣存放2的地址就會被丟棄,後續鏈表保存的數據也隨之無法訪問。而是應該設置一個臨時指針tmp,先暫時指向P->next指向的地址空間,保存原鏈表後續數據。然後再讓P->next指向NewH,最後P=tmp就可以取回原鏈表的數據了,所有循環訪問也可以繼續展開下去。
指針繼續向後移動,直到P指針指向NULL停止迭代。
最後一步:
2) 遞歸實現。
我們再來看看遞歸實現鏈表翻轉的實現,前面非遞歸方式是從前面數1開始往後依次處理,而遞歸方式則恰恰相反,它先循環找到最後面指向的數5,然後從5開始處理依次翻轉整個鏈表。
首先指針H迭代到底如下圖所示,並且設置一個新的指針作爲翻轉後的鏈表的頭。由於整個鏈表翻轉之後的頭就是最後一個數,所以整個過程NewH指針一直指向存放5的地址空間。
然後H指針逐層返回的時候依次做下圖的處理,將H指向的地址賦值給H->next->next指針,並且一定要記得讓H->next =NULL,也就是斷開現在指針的鏈接,否則新的鏈表形成了環,下一層H->next->next賦值的時候會覆蓋後續的值。
繼續返回操作:
上圖第一次如果沒有將存放4空間的next指針賦值指向NULL,第二次H->next->next=H,就會將存放5的地址空間覆蓋爲3,這樣鏈表一切都大亂了。接着逐層返回下去,直到對存放1的地址空間處理。
返回到頭:
三、以下是具體的代碼實現
<?php
class Node{
public $next=null;
public $data;
public function __construct($data=''){
$this->data=$data;
}
}
//新增
function addNode($head,$data){
$cur=$head;
while($cur->next!=null){
$cur=$cur->next;
}
$node=new Node($data);
$cur->next=$node;
}
//遍歷
function showNode($head){
$cur=$head;
while($cur->next!=null){
$cur=$cur->next;
echo $cur->data.PHP_EOL;
}
}
//feidigui非遞歸
function reversNode($head){
if($head==null){
return false;
}
$new=null;
$cur=$head;
while($cur!=null){
$temp=$cur->next;
$cur->next=$new;
$new=$cur;
$cur=$temp;
}
return $new;
}
//遞歸方式實現
function reversRecursionNode($head){
if($head->next==null){
return $head ;
}
$phead=reversRecursionNode($head->next);
$head->next->next=$head;
$head->next=null;
return $phead;
}
function test(){
$head=new Node();
addNode($head,'A');
addNode($head,'B');
addNode($head,'C');
addNode($head,'D');
showNode($head);
echo '--------------';
//$new=reversNode($head);
$new=reversRecursionNode($head);
echo'-----------------';
showNode($new);
echo'------------------------';
$head=new Node();
$head->next=$new;
showNode($head);
}
test();
?>
搬磚不容易,喜歡就賞點。