Structures_LinkedList_Single
[ class tree: Structures_LinkedList_Single ] [ index: Structures_LinkedList_Single ] [ all elements ]

Source for file Double.php

Documentation is available at Double.php

  1. <?php
  2.  
  3. /* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker textwidth=80: */
  4.  
  5. /**
  6.  * Linked list structure
  7.  * 
  8.  * This package implements a doubly linked list structure. Each node
  9.  * (Structures_LinkedList_DoubleNode object) in the list
  10.  * (Structures_LinkedList_Double) knows the previous node and the next
  11.  * node in the list. Unlike an array, you can insert or delete nodes at
  12.  * arbitrary points in the list.
  13.  *
  14.  * If your application normally traverses the linked list in a forward-only
  15.  * direction, use the singly-linked list implemented by
  16.  * {@link Structures_LinkedList_Single}. If, however, your application
  17.  * needs to traverse the list backwards, or insert nodes into the list before
  18.  * other nodes in the list, use the double-linked list implemented by
  19.  * {@link Structures_LinkedList_Double} to give your application better
  20.  * performance at the cost of a slightly larger memory footprint.
  21.  *
  22.  * Structures_LinkedList_Double implements the Iterator interface so control
  23.  * structures like foreach($list as $node) and while($list->next()) work
  24.  * as expected.
  25.  *
  26.  * To use this package, derive a child class from
  27.  * Structures_LinkedList_DoubleNode  and add data to the object. Then use the
  28.  * Structures_LinkedList_Double class to access the nodes.
  29.  *
  30.  * PHP version 5
  31.  *
  32.  * LICENSE:  Copyright 2006 Dan Scott
  33.  *
  34.  * Licensed under the Apache License, Version 2.0 (the "License"); you may
  35.  * not use this file except in compliance with the License. You may obtain
  36.  * a copy of the License at
  37.  *
  38.  *     http://www.apache.org/licenses/LICENSE-2.0
  39.  *
  40.  * Unless required by applicable law or agreed to in writing, software
  41.  * distributed under the License is distributed on an "AS IS" BASIS,
  42.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  43.  * See the License for the specific language governing permissions and
  44.  * limitations under the License.
  45.  *
  46.  * @category   Structures
  47.  * @package    Structures_LinkedList_Single
  48.  * @author     Dan Scott <dscott@laurentian.ca>
  49.  * @copyright  2006 Dan Scott
  50.  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
  51.  * @version    CVS: $Id: Double.php,v 1.8 2008/08/25 03:56:15 dbs Exp $
  52.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  53.  * @example    double_link_example.php
  54.  *
  55.  * @todo Add some actual error conditions
  56.  ***/
  57.  
  58. require_once 'PEAR/Exception.php';
  59. require_once 'Single.php';
  60.  
  61. // {{{ class Structures_LinkedList_Double
  62. /**
  63.  * The Structures_LinkedList_Double class represents a linked list structure
  64.  * composed of {@link Structures_LinkedList_DoubleNode} objects.
  65.  *
  66.  * @category   Structures
  67.  * @package    Structures_LinkedList_Single
  68.  * @author     Dan Scott <dscott@laurentian.ca>
  69.  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
  70.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  71.  */
  72. class Structures_LinkedList_Double extends Structures_LinkedList_Single implements Iterator {
  73.     // {{{ properties
  74.     /**
  75.      * Tail node of the linked list
  76.      * @var Structures_LinkedList_DoubleNode 
  77.      */
  78.     protected $tail_node;
  79.     // }}}
  80.  
  81.     // {{{ Constructor: function __construct()
  82.     /**
  83.      * Structures_LinkedList_Double constructor
  84.      *
  85.      * @param Structures_LinkedList_DoubleNode $root root node for the
  86.      *  linked list
  87.      */
  88.     function __construct(Structures_LinkedList_DoubleNode $root = null)
  89.     {
  90.         if ($root{
  91.             $this->tail_node = $root;
  92.         else {
  93.             $this->tail_node = null;
  94.         }
  95.         parent::__construct($root);
  96.     }
  97.     // }}}
  98.  
  99.     // {{{ Destructor: function __destruct()
  100.     /**
  101.      * Structures_LinkedList_Single destructor
  102.      *
  103.      * If we do not destroy all of the references in the linked list,
  104.      * we will quickly run out of memory for large / complex structures.
  105.      *
  106.      * @param Structures_LinkedList_SingleNode $root root node for the
  107.      *  linked list
  108.      */
  109.     function __destruct()
  110.     {
  111.         /*
  112.          * Starting with root node, set last node = root_node
  113.          *   get next node
  114.          *   if next node exists:
  115.          *     delete last node's references to next node and previous node
  116.          *     make the old next node the new last node
  117.          */
  118.         if (!$last_node $this->root_node{
  119.             return;
  120.         }
  121.         while (($next_node $last_node->next()) !== false{
  122.             $last_node->setNext(null);
  123.             $last_node->setPrevious(null);
  124.             $last_node $next_node;
  125.         }
  126.         $this->current = null;
  127.         $this->root_node = null;
  128.         $this->tail_node = null;
  129.         $last_node = null;
  130.         $next_node = null;
  131.     }
  132.     // }}}
  133.  
  134.     // {{{ function end()
  135.     /**
  136.      * Sets the pointer for the linked list to its last node
  137.      *
  138.      * @return Structures_LinkedList_DoubleNode last node in the linked list
  139.      */
  140.     public function end()
  141.     {
  142.         if ($this->tail_node{
  143.             $this->current = $this->tail_node;
  144.         else {
  145.             $this->current = null;
  146.         }
  147.         return $this->current;
  148.     }
  149.     // }}}
  150.  
  151.     // {{{ function previous()
  152.     /**
  153.      * Sets the pointer for the linked list to the previous node and
  154.      * returns that node
  155.      *
  156.      * @return Structures_LinkedList_DoubleNode previous node in the linked list
  157.      */
  158.     public function previous()
  159.     {
  160.         if (!$this->current()->previous()) {
  161.             return false;
  162.         }
  163.         $this->current = $this->current()->previous();
  164.         return $this->current();
  165.     }
  166.     // }}}
  167.  
  168.     // {{{ function insertNode()
  169.     /**
  170.      * Inserts a {@link Structures_LinkedList_DoubleNode} object into the linked
  171.      * list, based on a reference node that already exists in the list.
  172.      *
  173.      * @param Structures_LinkedList_DoubleNode $new_node New node to add to
  174.      *  the list
  175.      * @param Structures_LinkedList_DoubleNode $existing_node Reference
  176.      *  position node
  177.      * @param bool $before Insert new node before or after the existing node
  178.      * @return bool Success or failure
  179.      ***/
  180.     public function insertNode(Structures_LinkedList_SingleNode $new_nodeStructures_LinkedList_SingleNode $existing_node$before = false)
  181.     {
  182.         if (!$this->root_node{
  183.             $this->__construct($new_node);
  184.         }
  185.  
  186.         // Now add the node according to the requested mode
  187.         switch ($before{
  188.  
  189.         case true:
  190.             $previous_node $existing_node->previous();
  191.             if ($previous_node{
  192.                 $previous_node->setNext($new_node);
  193.                 $new_node->setPrevious($previous_node);
  194.             else {
  195.                 // The existing node must be root node; make new node root
  196.                 $this->root_node = $new_node;
  197.                 $new_node->setPrevious();
  198.             }
  199.             $new_node->setNext($existing_node);
  200.             $existing_node->setPrevious($new_node);
  201.  
  202.             break;
  203.  
  204.         case false:
  205.             $new_node->setPrevious($existing_node);
  206.             $next_node $existing_node->next();
  207.             if ($next_node{
  208.                 $new_node->setNext($next_node);
  209.                 $next_node->setPrevious($new_node);
  210.             else {
  211.                 // The existing node must have been the tail node
  212.                 $this->tail_node = $new_node;
  213.             }
  214.             $existing_node->setNext($new_node);
  215.  
  216.             break;
  217.  
  218.         }
  219.  
  220.         return true;
  221.     }
  222.     // }}}
  223.  
  224.     // {{{ protected function _getTailNode()
  225.     /**
  226.      * Returns the tail node of the linked list.
  227.      *
  228.      * This is a cheap operation for a doubly-linked list.
  229.      *
  230.      * @param Structures_LinkedList_DoubleNode $new_node New node to append
  231.      * @return bool Success or failure
  232.      ***/
  233.     protected function _getTailNode()
  234.     {
  235.         return $this->tail_node;
  236.     }
  237.     // }}}
  238.  
  239.     // {{{ function deleteNode()
  240.     /**
  241.      * Deletes a {@link Structures_LinkedList_DoubleNode} from the list.
  242.      *
  243.      * @param Structures_LinkedList_DoubleNode $node Node to delete.
  244.      */
  245.     public function deleteNode(Structures_LinkedList_SingleNode $node)
  246.     {
  247.         /* If this is the root node, and there are more nodes in the list,
  248.          * make the next node the new root node before deleting this node.
  249.          */
  250.         if ($node === $this->root_node{
  251.             $this->root_node = $node->next();
  252.         }
  253.         
  254.         /* If this is the tail node, and there are more nodes in the list,
  255.          * make the previous node the tail node before deleting this node
  256.          */
  257.         if ($node === $this->tail_node{
  258.             $this->tail_node = $node->previous();
  259.         }
  260.  
  261.         /* If this is the current node, and there are other nodes in the list,
  262.          * try making the previous node the current node so that next() works
  263.          * as expected.
  264.          *
  265.          * If that fails, make the next node the current node.
  266.          *
  267.          * If that fails, null isn't such a bad place to be.
  268.          */
  269.         if ($node === $this->current{
  270.             if ($node->previous()) {
  271.                 $this->current = $node->previous();
  272.             elseif ($node->next()) {
  273.                 $this->current = $node->next();
  274.             else {
  275.                 $this->current = null;
  276.             }
  277.         }
  278.         $node->__destruct();
  279.     }
  280.     // }}}
  281.  
  282. }
  283. // }}}
  284.  
  285. // {{{ class Structures_LinkedList_DoubleNode
  286. /**
  287.  * The Structures_LinkedList_DoubleNode class represents a node in a
  288.  * {@link Structures_LinkedList_Double} linked list structure.
  289.  *
  290.  * @category   Structures
  291.  * @package    Structures_LinkedList_Single
  292.  * @author     Dan Scott <dscott@laurentian.ca>
  293.  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
  294.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  295.  */
  296.     // {{{ properties
  297.     /**
  298.      * Previous node in the linked list
  299.      * @var Structures_LinkedList_DoubleNode 
  300.      */
  301.     protected $previous;
  302.     // }}}
  303.  
  304.     // {{{ Constructor: function __construct()
  305.     /**
  306.      * Structures_LinkedList_DoubleNode constructor
  307.      */
  308.     public function __construct()
  309.     {
  310.         $this->next = null;
  311.         $this->previous = null;
  312.     }
  313.     // }}}
  314.  
  315.     // {{{ Destructor: function __destruct()
  316.     /**
  317.      * Removes node from the list, adjusting the related nodes accordingly.
  318.      *
  319.      * This is a problem if the node is the root node for the list.
  320.      * At this point, however, we do not have access to the list itself. Hmm.
  321.      */
  322.     public function __destruct()
  323.     {
  324.         $next $this->next();
  325.         $previous $this->previous();
  326.         if ($previous && $next{
  327.             $previous->setNext($next);
  328.             $next->setPrevious($previous);
  329.         elseif ($previous{
  330.             $previous->setNext();
  331.         elseif ($next{
  332.             $next->setPrevious();
  333.         }
  334.     }
  335.     // }}}
  336.  
  337.     // {{{ function previous()
  338.     /**
  339.      * Return the previous node in the linked list
  340.      *
  341.      * @return Structures_LinkedList_DoubleNode previous node in the linked list
  342.      */
  343.     public function previous()
  344.     {
  345.         if ($this->previous{
  346.             return $this->previous;
  347.         else {
  348.             return false;
  349.         }
  350.     }
  351.     // }}}
  352.  
  353.     // {{{ function setPrevious()
  354.     /**
  355.      * Sets the pointer for the previous node in the linked list
  356.      * to the specified node
  357.      *
  358.      * @param Structures_LinkedList_DoubleNode $node new previous node
  359.      *  in the linked list
  360.      * @return Structures_LinkedList_DoubleNode new previous node in
  361.      *  the linked list
  362.      */
  363.     public function setPrevious(Structures_LinkedList_SingleNode $node = null)
  364.     {
  365.         $this->previous = $node;
  366.         return $this->previous;
  367.     }
  368.     // }}}
  369.  
  370. }
  371. // }}}
  372.  
  373. ?>

Documentation generated on Wed, 27 Aug 2008 23:30:29 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.