【问题标题】:php circular linked list implementationphp循环链表实现
【发布时间】:2012-10-26 11:52:21
【问题描述】:

我写了这个类来实现链表:

class Node{
    public $data;
    public $link;

    function __construct($data, $next = NULL){
        $this->data = $data;
        $this->link = $next;
    }    
}

class CircularLinkedList{
    private $first;
    private $current;
    private $count;

    function __construct(){
        $this->count = 0;
        $this->first = null;
        $this->current = null;
    }

    function isEmpty(){
        return ($this->first == NULL);
    }

    function push($data){
        //line 30
        $p = new Node($data, $this->first);
        if($this->isEmpty()){
            $this->first = $p;
            $this->current = $this->first;
        }
        else{           
            $q = $this->first;
            //line 38
            while($q->link != $this->first)
                $q = $q->link;
            $q->link = $p;    
        }
        $this->count++;       
    }

    function find($value){
        $q = $this->first;
        while($q->link != null){
            if($q->data == $value)
                $this->current = $q;
            $q = $q->link;    
        }
        return false;      
    }

    function getNext(){
        $result = $this->current->data;
        $this->current = $this->current->link;
        return $result;        
    }
}  

但是当我尝试推动一些价值时,

$ll = new CircularLinkedList();

$ll->push(5);
$ll->push(6);
$ll->push(7);
$ll->push(8);
$ll->push(9);
$ll->push(10);

//$ll->find(7);

for($j=0;$j<=30;$j++){
    $result = $ll->getNext();
    echo $result."<br />";
}

脚本在第二次推送时挂起并给出max_execution_time 错误。

如果我将 cals 的第 30 行和第 38 行更改为正常的 LinkedList,则效果很好。 (通过删除最后一个节点链接到第一个节点)。

那么问题是什么以及如何解决呢?

更新:通过将 push() 函数更改为 this ,它可以作为线性链表正常工作:

function push($data){
    $p = new Node($data);
    if($this->isEmpty()){
        $this->first = $p;
        $this->current = $this->first;
    }
    else{
        $q = $this->first;
        while($q->link != null)
            $q = $q->link;
        $q->link = $p;    
    }
    $this->count++;       
}

【问题讨论】:

  • 我的假设是您的 链接 不正确。因此第 38 行是一个无限循环。一些调试可能会证明这一点。
  • 我知道问题出在第 38 行。但逻辑似乎是正确的。问题是如何调试它
  • 你检查过SplDoublyLinkedList 和朋友吗?你可能不必自己做这一切。可以扩展一个 SPL 类 php.net/manual/en/class.spldoublylinkedlist.php
  • @Kris:它不支持循环链表和我需要的一些功能,扩展该类并进行修改可能会再次产生类似的问题!

标签: php linked-list


【解决方案1】:

对于线性链表 - 更改以下内容:

      function push($data){

       if($this->isEmpty()){
         $this->first   = new Node($data);
         $this->current = $this->first;
         $this->count++;
       }
       else{

        $this->current->link = new Node($data);
        $this->current = $this->current->link;
        $this->count++;

      }

    }

这个结构产生:

    CircularLinkedList Object
    (
      [first:CircularLinkedList:private] => Node Object
      (
        [data] => 2
        [link] => Node Object
            (
                [data] => 10
                [link] => Node Object
                    (
                        [data] => 3
                        [link] => Node Object
                            (
                                [data] => 9
                                [link] => 
                            )

                    )

            )

    )

    [current:CircularLinkedList:private] => Node Object
    (
        [data] => 9
        [link] => 
    )

    [count:CircularLinkedList:private] => 4
 )

对于循环 - 更改为:

     function push($data){

       if($this->isEmpty()){
         $this->first   = new Node($data);
         $this->current = $this->first;
         $this->count++;
       }
       else{

        $this->current->link = new Node($data, $this->first);
        $this->current = $this->current->link;
        $this->count++;

      }

    }

这个结构产生:

    CircularLinkedList Object
    (
      [first:CircularLinkedList:private] => Node Object
      (
        [data] => 2
        [link] => Node Object
            (
                [data] => 10
                [link] => Node Object
                    (
                        [data] => 3
                        [link] => Node Object
                            (
                                [data] => 9
                                [link] => Node Object
       *RECURSION*
                            )

                    )

            )

       )

    [current:CircularLinkedList:private] => Node Object
    (
        [data] => 9
        [link] => Node Object
            (
                [data] => 2
                [link] => Node Object
                    (
                        [data] => 10
                        [link] => Node Object
                            (
                                [data] => 3
                                [link] => Node Object
         *RECURSION*
                            )

                    )

            )

     )

    [count:CircularLinkedList:private] => 4
   )

【讨论】:

  • 嗨,如果我想在第一个位置插入一个新节点,你能告诉我应该改变什么推送方法
【解决方案2】:

你可以使用

$ll = new CircularLinkedList();

$ll->push(5);
$ll->push(6);
$ll->push(7);
$ll->push(8);
$ll->push(9);
$ll->push(10);
echo "<pre>";

用法

echo count($ll); // returns 6 

$ll->find(7);
echo $ll->getCurrent(); // returns 7


$ll->reset(); // Reset from current position to beginning

while ( $ll->isValid() ) {
    echo $ll->getCurrent() . "<br />";
    $ll->getNext();
}

输出

5
6
7
8
9
10

类节点

class Node {
    public $data;
    public $link;

    function __construct($data, $next = NULL) {
        $this->data = $data;
        $this->link = $next;
    }

    function __toString() {
        return "$this->data";
    }
}

类 CircularLinkedList

class CircularLinkedList implements Countable {
    private $data;
    private $current;
    private $count;

    function __construct() {
        $this->count = 0;
        $this->data = null;
        $this->current = null;
    }

    function isEmpty() {
        return ($this->data == NULL);
    }

    function push($data) {
        $p = new Node($data);
        if ($this->isEmpty()) {
            $this->data = $p;
            $this->current = $this->data;
        } else {
            $this->current->link = $p ;
            $this->current = $this->current->link;
        }
        $this->count ++;
    }

    function find($value) {
        $q = $this->data;
        while ( $q->link != null ) {
            if ($q->data == $value)
                $this->current = $q;
            $q = $q->link;
        }
        return false;
    }

    function getCurrent() {
        return $this->current;
    }

    function getNext() {
        $this->current = $this->current->link;
    }

    function hasNext() {
        return isset($this->current->link);
    }

    function isValid() {
        return isset($this->current);
    }

    function reset() {
        $this->current = $this->data;
    }

    function count() {
        return $this->count;
    }
}

【讨论】:

  • 我接受了乔布朗的回答,因为它更接近我的实现。还要为您的好答案 +1!
  • 我只是觉得for($j=0;$j&lt;=30;$j++){ 不是迭代CircularLinkedList 的好方法.. 必须创建与while 循环一起使用的方法..
  • 对不起,我忘了检查,这不是循环链接列表!它是线性的!
  • 阿里,第二个例子是循环的,因为最后一个节点链接指向第一个节点。因此,该结构告诉您它是递归的。
猜你喜欢
  • 1970-01-01
  • 2012-09-02
  • 2018-03-26
  • 1970-01-01
  • 2014-04-07
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多