1 雙連結串列
概括:雙向連結串列有兩個引用分別指向前後節點。優勢方便向前查詢資料。
請看上圖:data為資料,pre為指向前個節點的引用,next為指向後個節點的引用 。
完整程式碼塊:
<?php
/**
* 節點實現
*/
class Node
{
/**
* 資料元素
* @var
*/
public $item;
/**
* 前驅節點
* @var
*/
public $prev;
/**
* 後繼節點
* @var
*/
public $next;
/**
* Node constructor.
* @param $item
*/
public function __construct($item)
{
$this->item = $item;
$this->prev = null;
$this->next = null;
}
}
/**
* 雙向連結串列基本操作
*
* 1.isEmpty() 連結串列是否為空
* 2.length() 連結串列長度
* 3.travel() 遍歷整個連結串列
* 4.add(item) 連結串列頭部新增元素
* 5.append(item) 連結串列尾部新增元素
* 6.insert(pos, item) 指定位置新增元素
* 7.remove(item) 刪除節點
* 8.search(item) 查詢節點是否存在
*/
class DoubleLink
{
/**
* 頭節點
* @var
*/
private $head;
/**
* SingleLink constructor.
*/
public function __construct()
{
$this->head = null;
}
/**
* 連結串列是否為空
* @return bool
*/
public function isEmpty()
{
return is_null($this->head);
}
/**
* 連結串列長度
* @return int
*/
public function length()
{
$cur = $this->head;
$count = 0;
while(!is_null($cur)){
$count++;
$cur = $cur->next;
}
return $count;
}
/**
* 遍歷整個連結串列
*/
public function travel()
{
$cur = $this->head;
$tmp = [];
while (!is_null($cur)) {
array_push($tmp,$cur->item);
$cur = $cur->next;
}
return $tmp;
}
/**
* 連結串列頭部新增元素
* @param $item
*/
public function add($item)
{
$node = new Node($item);
if($this->isEmpty()){
$this->head = $node;
}else{
//待插入節點後繼節點為原本頭節點
$node->next = $this->head;
//待插入節點為原本頭節點的前驅節點
$this->head->prev = $node;
//待插入節點變為頭節點
$this->head = $node;
}
}
/**
* 連結串列尾部新增元素
* @param $item
*/
public function append($item)
{
$node = new Node($item);
if($this->isEmpty()){
$this->head = $node;
}else{
//移動到尾節點
$cur = $this->head;
while (!is_null($cur->next)){
$cur = $cur->next;
}
//原本尾節點next指向待插入節點
$cur->next = $node;
//待插入節點prev指向原本尾節點
$node->prev = $cur;
}
}
/**
* 指定位置新增元素
* @param $pos
* @param $item
*/
public function insert($pos, $item)
{
switch ($pos){
//若指定位置pos為第一個元素之前,則執行頭部插入
case $pos <= 0:
$this->add($item);
break;
//若指定位置超過連結串列尾部,則執行尾部插入
case $pos > ($this->length() - 1):
$this->append($item);
break;
//找到位置
default:
$node = new Node($item);
$count = 0;
$cur = $this->head;
//移到指定位置的前一個位置
while ($count < ($pos - 1)){
$count++;
$cur = $cur->next;
}
$node->prev = $cur;
$node->next = $cur->next;
$cur->next->prev = $node;
$cur->next = $node;
}
}
/**
* 刪除節點
* @param $item
*/
public function remove($item)
{
if($this->isEmpty()){
return;
}
$cur = $this->head;
//如果第一個就是刪除的節點
if($cur->item == $item){
//如果只有這一個節點
if(is_null($cur->next)){
$this->head = null;
}else{
$cur->next->prev = null;
$this->head = $cur->next;
}
return;
}
while (!is_null($cur)){
//找到元素
if($cur->item == $item){
$cur->prev->next = $cur->next;
$cur->next->prev = $cur->prev;
break;
}
$cur = $cur->next;
}
}
/**
* 查詢節點是否存在
* @param $item
* @return bool
*/
public function search($item)
{
$cur = $this->head;
while (!is_null($cur)){
if($cur->item == $item){
return true;
}
$cur = $cur->next;
}
return false;
}
}
$s = new DoubleLink();
$s->add('23');
$s->add('er');
$s->add('33');
//$s->append('56');
//$s->insert(2,'2222');
//echo $s->length();
//var_dump($s->travel());
//var_dump($s->search('er'));
//$s->remove('er');
var_dump($s->travel());
2 分析程式碼塊 具體分析到程式碼註釋哦 ~
定義一個節點物件
/**
* 節點實現
*/
class Node
{
/**
* 資料元素
* @var
*/
public $item;
/**
* 前驅節點
* @var
*/
public $prev;
/**
* 後繼節點
* @var
*/
public $next;
/**
* Node constructor.
* @param $item
*/
public function __construct($item)
{
$this->item = $item;
$this->prev = null;
$this->next = null;
}
}
連結串列頭部新增元素 小夥伴們要注意哦 這個必須要執行三步驟
/**
* 連結串列頭部新增元素
* @param $item
*/
public function add($item)
{
$node = new Node($item);//申明一個節點
if($this->isEmpty()){//如果頭部節點為空的情況下
$this->head = $node;//把頭部節點定義為當前定義的節點
}
//如果已經存在頭部節點的話
else{
//第一步:將插入的節點的下一個節點為頭部節點
$node->next = $this->head;
//第二步:將頭部的上一個節點為當前節點
$this->head->prev = $node;
//第三步:將頭部節點替換成當前節點
$this->head = $node;
}
}
/**
* 連結串列是否為空
* @return bool
*/
public function isEmpty()
{
return is_null($this->head);
}
$s = new DoubleLink();
$s->add('23');
$s->add('er');
$s->add('33');
連結串列尾部新增元素 小夥伴們要注意哦 看我畫的重點的步驟
/**
* 連結串列尾部新增元素
* @param $item
*/
public function append($item)
{
$node = new Node($item);//定義一個節點物件
if($this->isEmpty()){//如果頭部節點為空的情況下
$this->head = $node;//把頭部節點定義為當前定義的節點
}else{
//移動到尾節點 開始 此次為重點
$cur = $this->head;//定義一個頭部節點
//這邊為了找到最後的尾部節點在哪裡 因為小哥哥要在尾部插入節點啊
while (!is_null($cur->next)){//迴圈輸出下一個節點 不為空的情況下
$cur = $cur->next;//將當前的節點定義為找到的尾部節點的下一個指標 因為是當前的節點
}
//移動到尾節點 結束
//原本尾節點next指向待插入節點
$cur->next = $node;//當前的下一個節點為要插入的節點
//待插入節點prev指向原本尾節點
$node->prev = $cur;//要插入的上一個節點為尾節點
}
}
$s->append('56');
指定位置新增元素 小夥伴們要注意哦 看我畫的重點的步驟 四步驟狠關鍵
/**
* 指定位置新增元素
* @param $pos
* @param $item
*/
public function insert($pos, $item)
{
switch ($pos){
//若指定位置pos為第一個元素之前,則執行頭部插入
case $pos <= 0:
$this->add($item);
break;
//若指定位置超過連結串列尾部,則執行尾部插入
case $pos > ($this->length() - 1):
$this->append($item);
break;
//找到位置 以上二點都不是的情況下怎麼辦呢
default:
$node = new Node($item);//先定義一個節點物件
$count = 0;//定一個數量為0
$cur = $this->head;//當前節點為頭部節點
//移到指定位置的前一個位置
while ($count < ($pos - 1)){ //這邊迴圈要移動到哪個位置上
$count++;
$cur = $cur->next;//把要插入到哪個位置上的節點 拿出來
}
//這裡很重要
$node->prev = $cur;//第一步:要插入的節點上一個就是拿出來的當前節點
$node->next = $cur->next;//第二步:要插入的節點的下一個節點 就是拿出來的當前的節點的下一個節點
$cur->next->prev = $node;//第三步:這邊是關鍵步驟:把拿出來的下一個節點的上一個節點 指向要插入的節點
$cur->next = $node;//第四步:把拿出來的下一個節點指向當前要插入的節點
}
}
$s->insert(2,'2222');
刪除節點: 小夥伴們要注意哦 這邊刪除的話看重點 刪除要處理前後節點的指標指向才能完全真正的刪除
/**
* 刪除節點
* @param $item
*/
public function remove($item)
{
if($this->isEmpty()){//判斷頭部是否為空 如果為空就不用處理了
return;
}
$cur = $this->head;//先定義一個當前元素 為頭部節點
//如果第一個就是刪除的節點
if($cur->item == $item){//如果當前節點的值為要刪除的值
//如果只有這一個節點
if(is_null($cur->next)){//如果這個節點的下一個節點為空的話
$this->head = null;//直接把頭部節點為null
}
//如果頭部節點有下一個節點的話
else{
$cur->next->prev = null;//第一步:就把頭部節點的下一個節點的上一個節點為null
$this->head = $cur->next;//第二步:就把頭部節點指向當前節點的下一個節點
}
return;
}
//如果要刪除的值不等於頭部節點的值的話 就要迴圈查詢要刪除的節點咯
while (!is_null($cur)){
//找到元素
if($cur->item == $item){//查詢到了
$cur->prev->next = $cur->next;//第一步:當前的上一個節點的下一個節點 替換為當前要刪除的節點的下一個節點
$cur->next->prev = $cur->prev;//第二步:當前的下一個節點的上一個節點 替換為當前要刪除的節點的上一個節點
break;
}
$cur = $cur->next;//定義當前的節點為下一個節點 作用迴圈使用
}
}
$s->remove('33');
查詢節點
/**
* 查詢節點是否存在
* @param $item
* @return bool
*/
public function search($item)
{
$cur = $this->head;//定義頭部節點
while (!is_null($cur)){//迴圈節點
if($cur->item == $item){//如果找到就找到了 很簡單吧
return true;
}
$cur = $cur->next;
}
return false;
}
var_dump($s->search('er'));
迴圈節點
/**
* 遍歷整個連結串列
*/
public function travel()
{
$cur = $this->head;
var_dump($cur);die();
$tmp = [];//定義一個陣列
while (!is_null($cur)) {//依次迴圈
array_push($tmp,$cur->item);//把值放到陣列裡面
$cur = $cur->next;
}
return $tmp;
}