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