Skip to content

Commit

Permalink
php 06_linkedlist
Browse files Browse the repository at this point in the history
  • Loading branch information
lide committed Oct 9, 2018
1 parent 61c8385 commit 05b6179
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 0 deletions.
2 changes: 2 additions & 0 deletions php/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
vendor
210 changes: 210 additions & 0 deletions php/06_linkedlist/SingleLinkedList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
<?php
/**
* User: lide01
* Date: 2018/10/8 11:55
* Desc:
*/

namespace Algo_06;


/**
* 单链表
*
* Class SingleLinkedList
*
* @package Algo_06
*/
class SingleLinkedList
{
/**
* 单链表头结点(哨兵节点)
*
* @var SingleLinkedListNode
*/
public $head;

/**
* 单链表长度
*
* @var
*/
private $length;

/**
* 初始化单链表
*
* SingleLinkedList constructor.
*/
public function __construct()
{
$this->head = new SingleLinkedListNode();
$this->length = 0;
}

/**
* 获取链表长度
*
* @return int
*/
public function getLength()
{
return $this->length;
}

/**
* 插入数据 采用头插法 插入新数据
*
* @param $data
*
* @return SingleLinkedListNode|bool
*/
public function insert($data)
{
return $this->insertDataAfter($this->head, $data);
}

/**
* 删除节点
*
* @param SingleLinkedListNode $node
*
* @return bool
*/
public function delete(SingleLinkedListNode $node)
{
if (null == $node) {
return false;
}

// 获取待删除节点的前置节点
$preNode = $this->getPreNode($node);

// 修改指针指向
$preNode->next = $node->next;
unset($node);

$this->length--;
return true;
}

/**
* 通过索引获取节点
*
* @param int $index
*
* @return SingleLinkedListNode|null
*/
public function getNodeByIndex($index)
{
if ($index >= $this->length) {
return null;
}

$cur = $this->head->next;
for ($i = 0; $i < $index; ++$i) {
$cur = $cur->next;
}

return $cur;
}

/**
* 获取某个节点的前置节点
*
* @param SingleLinkedListNode $node
*
* @return SingleLinkedListNode|bool
*/
public function getPreNode(SingleLinkedListNode $node)
{
if (null == $node) {
return false;
}

$curNode = $this->head;
$preNode = $this->head;
// 遍历找到前置节点 要用全等判断是否是同一个对象
// http://php.net/manual/zh/language.oop5.object-comparison.php
while ($curNode !== $node) {
$preNode = $curNode;
$curNode = $curNode->next;
}

return $preNode;
}

/**
* 输出单链表 当data的数据为可输出类型
*
* @return bool
*/
public function printList()
{
if (null == $this->head->next) {
return false;
}

$curNode = $this->head;
while ($curNode->next != null) {
echo $curNode->next->data . ' ';

$curNode = $curNode->next;
}
echo PHP_EOL;

return true;
}

/**
* 在某个节点后插入新的节点
*
* @param SingleLinkedListNode $originNode
* @param $data
*
* @return SingleLinkedListNode|bool
*/
public function insertDataAfter(SingleLinkedListNode $originNode, $data)
{
// 如果originNode为空,插入失败
if (null == $originNode) {
return false;
}

// 新建单链表节点
$newNode = new SingleLinkedListNode();
// 新节点的数据
$newNode->data = $data;

// 新节点的下一个节点为源节点的下一个节点
$newNode->next = $originNode->next;
// 在originNode后插入newNode
$originNode->next = $newNode;

// 链表长度++
$this->length++;

return $newNode;
}

/**
* 在某个节点前插入新的节点(很少使用)
*
* @param SingleLinkedListNode $originNode
* @param $data
*
* @return SingleLinkedListNode|bool
*/
public function insertDataBefore(SingleLinkedListNode $originNode, $data)
{
// 如果originNode为空,插入失败
if (null == $originNode) {
return false;
}

// 先找到originNode的前置节点,然后通过insertDataAfter插入
$preNode = $this->getPreNode($originNode);

return $this->insertDataAfter($preNode, $data);
}
}
42 changes: 42 additions & 0 deletions php/06_linkedlist/SingleLinkedListNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* User: lide01
* Date: 2018/10/8 11:38
* Desc:
*/

namespace Algo_06;


/**
* 单链表节点
*
* Class SingleLinkedListNode
*
* @package Algo_06
*/
class SingleLinkedListNode
{
/**
* 节点中的数据域
*
* @var null
*/
public $data;

/**
* 节点中的指针域,指向下一个节点
*
* @var SingleLinkedListNode
*/
public $next;

/**
* SingleLinkedListNode constructor.
*/
public function __construct()
{
$this->data = null;
$this->next = null;
}
}
64 changes: 64 additions & 0 deletions php/06_linkedlist/main.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* User: lide01
* Date: 2018/10/8 11:55
* Desc:
*/

namespace Algo_06;
require_once '../vendor/autoload.php';

/**
* 判断链表保存的字符串是否是回文
*
* @param SingleLinkedList $list
*
* @return bool
*/
function isPalindrome(SingleLinkedList $list)
{
if ($list->getLength() <= 1) {
return true;
}

$pre = null;
$slow = $list->head->next;
$fast = $list->head->next;
$remainNode = null;

// 找单链表中点 以及 反转前半部分链表
while ($fast != null && $fast->next != null) {
$fast = $fast->next->next;

// 单链表反转关键代码 三个指针
$remainNode = $slow->next;
$slow->next = $pre;
$pre = $slow;
$slow = $remainNode;
}
// 链表长度为偶数的情况
if ($fast != null) {
$slow = $slow->next;
}

// 开始逐个比较
while ($slow != null) {
if ($slow->data != $pre->data) {
return false;
}
$slow = $slow->next;
$pre = $pre->next;
}

return true;
}

$list = new SingleLinkedList();
$list->insert('a');
$list->insert('b');
$list->insert('c');
$list->insert('c');
$list->insert('b');
$list->insert('a');

var_dump(isPalindrome($list));
10 changes: 10 additions & 0 deletions php/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 数据结构与算法之美PHP实现

### 项目运行
* 依赖composer自动加载,php目录下执行`composer dump-autoload`
* 项目代码均在mac&php7环境下跑通

### 项目实现
#### 06
* 单链表php实现
* 回文判断
11 changes: 11 additions & 0 deletions php/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "algo/php",
"description": "数据结构与算法之美php实现",
"type": "project",
"require": {},
"autoload": {
"psr-4": {
"Algo_06\\": "06_linkedlist/"
}
}
}

0 comments on commit 05b6179

Please sign in to comment.