實戰PHP數據結構基礎之雙鏈表

什麼是雙鏈表?

上一篇實戰PHP數據結構基礎之單鏈表說到git

單鏈表由一個一個的做爲節點的對象構成的,每個節點都有指向下一個節點的指針,最後一個節點的指針域指向空。每一個節點能夠存儲任何數據類型。github

而雙鏈表每一個節點有兩個指針域,分別指向前驅和後繼節點。單鏈表是單向的,而雙鏈表是雙向的。web

常見操做

對雙鏈表咱們常見的操做有以下:算法

  • insert
  • insertBefore
  • insertAfter
  • insertAtFirst
  • insertAtLast
  • deleteFirst
  • deleteLast
  • delete
  • reverse
  • getNthNode
  • ...

PHP語言實現

首先咱們根據定義實現一個雙鏈表的ListNode類。數據結構

class ListNode {
    public $data = null;
    public $next = null;
    public $prev = null;

    public function __construct(string $data) {
        $this->data = $data;
    }
}
複製代碼

再來看鏈表類,首先須要3個私有屬性,分別是頭節點、尾巴節點和長度。數據結構和算法

class DoubleLinkedList {
    private $head = null;
    private $last = null;
    private $length = 0;
}
複製代碼

接下來仍是老規矩,直接看如何實現第一個即經常使用的插入,這是是一個平均時間複雜度爲O(n)的操做。post

/** * 插入一個節點 * @param string|null $data * @return bool * complexity O(n) */
public function insert(string $data = null) {
    $newNode = new ListNode($data);
    if ($this->head) {
        $currentNode = $this->head;
        while ($currentNode) {
            if ($currentNode->next === null) {
                $currentNode->next = $newNode;
                $newNode->prev = $currentNode;
                $this->last = $newNode;
                $this->length++;
                return true;
            }

            $currentNode = $currentNode->next;
        }
    } else {
        $this->head = &$newNode;
        $this->last = $newNode;
        $this->length++;
        return true;
    }

}
複製代碼

再來看如何刪除節點。優化

/** * 刪除一個節點 * @param string $data * @return bool|ListNode * complexity O(n) */
public function delete(string $query = null) {
    if ($this->head) {
        $currentNode = $this->head;
        $prevNode = null;
    
        while ($currentNode) {
            if ($currentNode->data === $query) {
                if ($nextNode = $currentNode->next) {
                    if ($prevNode) {
                        $prevNode->next = $nextNode;
                        $nextNode->prev = $prevNode;
                    } else {
                        $this->head = $nextNode;
                        $nextNode->prev = null;
                    }
    
                    unset($currentNode);
                } else {
                    if ($prevNode) {
                        $this->last = $prevNode;
                        $prevNode->next = null;
                        unset($currentNode);
                    } else {
                        $this->head = null;
                        $this->last = null;
                    }
                }
    
                $this->length--;
                return true;
            }
    
            $prevNode = $currentNode;
            $currentNode = $currentNode->next;
        }
    }

    return false;
}
複製代碼

反轉雙鏈表也不是很複雜。this

public function reverse() {
    if ($this->head !== null) {

        if ($this->head->next !== null) {
            $reversedList = null;
            $currentNode = $this->head;

            while ($currentNode !== null) {
                $next = $currentNode->next;
                $currentNode->next = $reversedList;
                $currentNode->prev = $next;

                $reversedList = $currentNode;
                $currentNode = $next;

            }

            $this->last = $this->head;
            $this->head = $reversedList;
        }
    }
}
複製代碼

雙鏈表其餘操做的詳細實現能夠參考 這裏spa

雙鏈表是鏈表這種鏈式存取數據結構中相對於單鏈表比較特殊的部分,一樣屬於鏈表結構的還有單鏈表,環形鏈表和多鏈表。

專題系列

PHP基礎數據結構專題系列目錄地址:github.com/... 主要使用PHP語法總結基礎的數據結構和算法。還有咱們平常PHP開發中容易忽略的基礎知識和現代PHP開發中關於規範、部署、優化的一些實戰性建議,同時還有對Javascript語言特色的深刻研究。

相關文章
相關標籤/搜索