數據結構:鏈表(單鏈表)

1、鏈表php

  概念:鏈表[Linked List]是由一組沒必要相連(可連續可不連續)的內存結構(節點),按照特定的順序連接在一塊兒的抽象數據類型;數據結構

  分類:鏈表經常使用的大概有三類:單鏈表、雙向鏈表、循環鏈表(這篇文章主要講單鏈表)this

  操做:鏈表的核心操做主要有三個(查找遍歷、插入、刪除)spa

2、單鏈表3d

  

  上圖就是一個單鏈表的數據結構了,從上圖能夠看出,每一個節點包含兩個重要的元素(data、next),那麼什麼是單鏈表呢?指針

  概念:各個內存結構經過一個Next指針連接在一塊兒,每一個內存結構都存在後續的內存結構(鏈尾除外);內存域由兩部分組成(Data數據域Next指針域code

3、操做blog

  

  上圖展現了單鏈表的插入和刪除的過程,很清楚的可以知道是怎麼一回事,針對我這樣的小白來講,至少我看懂了;排序

  下面是本人結合上面的圖寫的代碼(隨便寫的,將就着看,代碼只是驗證你是否真的瞭解 該數據結構,因此理解了便可,沒有必要在乎代碼的好壞,謝謝!):遞歸

<?php
/***
 * 單鏈表數據結構
 * 鏈表是一種遞歸的數據結構,它或爲空(Null),或指向一個結點的引用,該結點還有一個元素和指向下一個鏈表的引用
 * 單鏈表的每一個節點由兩個元素組成:data、next
 */
class Node{
    public $data;
    public $next=null;
    public $linkedSize = 0; // 記錄鏈表的大小(每一個節點都保存了這個值爲0,其實也能夠保持個id,看我的習慣)
    public function __construct($data){
        $this->data = $data;
    }
}

class LinkedList{

    /***
     * 建立鏈表
     * @param array $data
     * @return Node|string
     */
    public static function createLinked($data=array())
    {
        if(empty($data))
            return '參數爲空';
        $header = new Node('');
        $headerObj = $header;
        foreach ($data as $key=>$val)
        {
            $nextHeader = new Node($val);
            $headerObj->next = $nextHeader;
            $headerObj = $nextHeader;
            $header->linkedSize++;
        }

        return $header;
    }

    /***
     * 遍歷鏈表數據
     * @param Node $header
     * @return bool
     */
    public static function selectLinkedList(Node $header)
    {
        $linkedObj = $header;
        $i = 0;
        while($linkedObj->next != null)
        {
            echo $i.' Node data:'.$linkedObj->next->data."\n";
            $linkedObj = $linkedObj->next;
            $i++;
        }
        return true;
    }

    /***
     * @param Node $header
     * @param $key
     * @param $data
     * @param string $lmr l 指定key的前邊插入 m 指定位置插入 r 指定位置的後邊插入
     * @return bool|string
     */
    public static function insertKeyLinkedList(Node $header, $key, $data, $lmr='r')
    {
        // 鏈表可能爲空(添加一個節點)
        if($header->linkedSize < 1)
        {
            $newHeader = new Node($data);
            $header->next = $newHeader;
            $header->linkedSize++;
            return true;
        }

        # 配置插入方向和位置
        $lmrKey = array('l', 'm', 'r');
        $lmrConfig = array(
            'l' => $key - 1,// 往指定位置的前邊插入數據
            'm' => $key, // 往指定位置插入數據
            'r' => $key + 1 // 往指定位置的後邊插入數據
        );

        // 驗證key的合法性
        if(!preg_match('/^[0-9]{1,}$/si', $key) || !in_array(trim($lmr), $lmrKey))
            return '請輸入正確的key和lmr方向';

        # 獲取真實的位置
        if(!isset($lmrConfig[trim($lmr)]))
            return '計算位置錯誤(可能參數有誤)';
        $positionKey = $lmrConfig[trim($lmr)];
        $maxSize = $header->linkedSize-1;
        if(trim($lmr) == 'r')
            $maxSize = $header->linkedSize;
        if($positionKey > $maxSize)
            return '未知的位置';

        $i = 0;
        $headerObj = $header;
        while($headerObj->next != null)
        {
            // 這裏有點相似我們常常用的冒泡排序,交換位置
            if($positionKey == $i || $positionKey < 0)
            {
                $newHeader = new Node($data);
                $temp = $headerObj->next;
                $headerObj->next = $newHeader;
                $newHeader->next = $temp;
                $header->linkedSize++;
                return true;
            }
            if(trim($lmr) == 'r' && ($i+1) == $maxSize) // 插入到末尾
            {
                $newHeader = new Node($data);
                $headerObj->next->next = $newHeader;
                $header->linkedSize++;
                return true;
            }

            $headerObj = $headerObj->next;
            $i++;
        }

        return true;
    }

    /***
     * @param Node $header
     * @param int $key
     * @return bool|string
     */
    public static function deleteKeyLinkedList(Node $header, $key=0)
    {
        if(!preg_match('/^[0-9]{1,}$/si', $key) || $key > ($header->linkedSize-1) || $key < 0)
            return '輸入的key不合法/當前位置沒有數據';

        if($header->next == null || $header->linkedSize < 1)
            return '鏈表中暫無數據';

        $i = 0;
        $position = $key;
        $headerObj = $header;
        while($headerObj->next != null)
        {
            if($i == $position)
            {
                $tmp = $headerObj->next->next;
                unset($headerObj->next);
                $headerObj->next = $tmp;
                $header->linkedSize--;
                return true;
            }
            $headerObj = $headerObj->next;
            $i++;
        }
        return true;
    }
}

# 建立鏈表
$data = array(22, 2, 90, 6, 43, 76, 89);
$header = LinkedList::createLinked($data);

# 遍歷單向鏈表
LinkedList::selectLinkedList($header);
echo "\n";

# 插入一個元素
$header = new Node('');
LinkedList::insertKeyLinkedList($header,6, 250, 'l');

# 插入後遍歷單向鏈表
LinkedList::selectLinkedList($header);
//var_dump($header);

// 刪除指定的節點
LinkedList::deleteKeyLinkedList($header, 1);

# 刪除後遍歷單向鏈表
LinkedList::selectLinkedList($header);

博客內容出自:https://www.jianshu.com/p/73d56c3d228c

相關文章
相關標籤/搜索