zoukankan      html  css  js  c++  java
  • 算法笔记-判断链表保存的字符串是否是回文

    <?php
    
    /**
     * 单链表节点
     *
     * Class SingleLinkedListNode
     *
     * @package Algo_06
     */
    class SingleLinkedListNode
    {
        /**
         * 节点中的数据域
         *
         * @var null
         */
        public $data;
    
        /**
         * 节点中的指针域,指向下一个节点
         *
         * @var SingleLinkedListNode
         */
        public $next;
    
        /**
         * SingleLinkedListNode constructor.
         *
         * @param null $data
         */
        public function __construct($data = null)
        {
            $this->data = $data;
            $this->next = null;
        }
    }
    /**
     * 单链表
     *
     * Class SingleLinkedList
     *
     * @package Algo_06
     */
    class SingleLinkedList
    {
        /**
         * 单链表头结点(哨兵节点)
         *
         * @var SingleLinkedListNode
         */
        public $head;
    
        /**
         * 单链表长度
         *
         * @var
         */
        private $length;
    
        /**
         * 初始化单链表
         *
         * SingleLinkedList constructor.
         *
         * @param null $head
         */
        public function __construct($head = null)
        {
            if (null == $head) {
                $this->head = new SingleLinkedListNode();
            } else {
                $this->head = $head;
            }
    
            $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 && $curNode != null) {
                $preNode = $curNode;
                $curNode = $curNode->next;
            }
    
            return $preNode;
        }
    
        /**
         * 输出单链表 当data的数据为可输出类型
         *
         * @return bool
         */
        public function printList()
        {
            if (null == $this->head->next) {
                return false;
            }
    
            $curNode = $this->head;
            // 防止链表带环,控制遍历次数
            $listLength = $this->getLength();
            while ($curNode->next != null && $listLength--) {
                echo $curNode->next->data . ' -> ';
    
                $curNode = $curNode->next;
            }
            echo 'NULL' . PHP_EOL;
    
            return true;
        }
    
        /**
         * 输出单链表 当data的数据为可输出类型
         *
         * @return bool
         */
        public function printListSimple()
        {
            if (null == $this->head->next) {
                return false;
            }
    
            $curNode = $this->head;
            while ($curNode->next != null) {
                echo $curNode->next->data . ' -> ';
    
                $curNode = $curNode->next;
            }
            echo 'NULL' . 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);
        }
    
        /**
         * 在某个节点后插入新的节点
         *
         * @param SingleLinkedListNode $originNode
         * @param SingleLinkedListNode $node
         *
         * @return SingleLinkedListNode|bool
         */
        public function insertNodeAfter(SingleLinkedListNode $originNode, SingleLinkedListNode $node)
        {
            // 如果originNode为空,插入失败
            if (null == $originNode) {
                return false;
            }
    
            $node->next = $originNode->next;
            $originNode->next = $node;
    
            $this->length++;
    
            return $node;
        }
    
        /**
         * 构造一个有环的链表
         */
        public function buildHasCircleList()
        {
            $data = [1, 2, 3, 4, 5, 6, 7, 8];
    
            $node0 = new SingleLinkedListNode($data[0]);
            $node1 = new SingleLinkedListNode($data[1]);
            $node2 = new SingleLinkedListNode($data[2]);
            $node3 = new SingleLinkedListNode($data[3]);
            $node4 = new SingleLinkedListNode($data[4]);
            $node5 = new SingleLinkedListNode($data[5]);
            $node6 = new SingleLinkedListNode($data[6]);
            $node7 = new SingleLinkedListNode($data[7]);
    
            $this->insertNodeAfter($this->head, $node0);
            $this->insertNodeAfter($node0, $node1);
            $this->insertNodeAfter($node1, $node2);
            $this->insertNodeAfter($node2, $node3);
            $this->insertNodeAfter($node3, $node4);
            $this->insertNodeAfter($node4, $node5);
            $this->insertNodeAfter($node5, $node6);
            $this->insertNodeAfter($node6, $node7);
    
            $node7->next = $node4;
        }
    }
    /**
     * 判断链表保存的字符串是否是回文
     *
     * @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));
  • 相关阅读:
    增删改查
    全局配置文件mappers_sql映射注册
    全局配置文件<typeAliases>别名配置
    接口式编程小结
    Mybatis_接口编程
    Mybatis_HelloWord
    xml中标签含义
    Spring中Bean的基本概念
    ACM 第十四天
    ACM 第十三天
  • 原文地址:https://www.cnblogs.com/rxbook/p/10338763.html
Copyright © 2011-2022 走看看