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

Source for file Single.php

Documentation is available at Single.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 singly linked list structure. Each node
  9.  * (Structures_LinkedList_SingleNode object) in the list
  10.  * (Structures_LinkedList_Single) knows the the next node in the list.
  11.  * Unlike an array, you can insert or delete nodes at arbitrary points
  12.  * 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_Single 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_SingleNode and add data to the object. Then use the
  28.  * Structures_LinkedList_Single 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: Single.php,v 1.7 2007/02/25 04:53:33 dbs Exp $
  52.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  53.  * @example    single_link_example.php
  54.  *
  55.  * @todo Add some actual error conditions
  56.  ***/
  57.  
  58. require_once 'PEAR/Exception.php';
  59.  
  60. // {{{ class Structures_LinkedList_Single
  61. /**
  62.  * The Structures_LinkedList_Single class represents a linked list structure
  63.  * composed of {@link Structures_LinkedList_SingleNode} objects.
  64.  *
  65.  * @category   Structures
  66.  * @package    Structures_LinkedList_Single
  67.  * @author     Dan Scott <dscott@laurentian.ca>
  68.  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
  69.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  70.  */
  71. class Structures_LinkedList_Single implements Iterator {
  72.     // {{{ properties
  73.     /**
  74.      * Current node in the linked list
  75.      * @var Structures_LinkedList_SingleNode 
  76.      */
  77.     protected $current;
  78.  
  79.     /**
  80.      * Root node of the linked list
  81.      * @var Structures_LinkedList_SingleNode 
  82.      */
  83.     protected $root_node;
  84.  
  85.     /**
  86.      * The linked list contains no nodes
  87.      */
  88.     const ERROR_EMPTY = -1;
  89.  
  90.     public static $messages = array(
  91.         self::ERROR_EMPTY => 'No nodes in this linked list' 
  92.     );
  93.     // }}}
  94.  
  95.     // {{{ Constructor: function __construct()
  96.     /**
  97.      * Structures_LinkedList_Single constructor
  98.      *
  99.      * @param Structures_LinkedList_SingleNode $root root node for the
  100.      *  linked list
  101.      */
  102.     function __construct(Structures_LinkedList_SingleNode $root = null)
  103.     {
  104.         if ($root{
  105.             $this->root_node = $root;
  106.             $this->current = $root;
  107.         else {
  108.             $this->root_node = null;
  109.             $this->current = null;
  110.         }
  111.     }
  112.     // }}}
  113.  
  114.     // {{{ Destructor: function __destruct()
  115.     /**
  116.      * Structures_LinkedList_Single destructor
  117.      *
  118.      * If we do not destroy all of the references in the linked list,
  119.      * we will quickly run out of memory for large / complex structures.
  120.      *
  121.      * @param Structures_LinkedList_SingleNode $root root node for the
  122.      *  linked list
  123.      */
  124.     function __destruct()
  125.     {
  126.         /*
  127.          * Starting with root node, set last node = root_node
  128.          *   get next node
  129.          *   if next node exists, delete last node reference to next node
  130.          */
  131.         if (!$last_node $this->root_node{
  132.             return;
  133.         }
  134.         while (($next_node $last_node->next()) !== false{
  135.             $last_node->setNext(null);
  136.             $temp_node $last_node;
  137.             $last_node $next_node;
  138.             unset($temp_node);
  139.         }
  140.         $this->current = null;
  141.         $this->root_node = null;
  142.         $last_node = null;
  143.         $next_node = null;
  144.     }
  145.     // }}}
  146.  
  147.     // {{{ function current()
  148.     /**
  149.      * Returns the current node in the linked list
  150.      *
  151.      * @return Structures_LinkedList_SingleNode current node in the linked list
  152.      */
  153.     public function current()
  154.     {
  155.         return $this->current;
  156.     }
  157.     // }}}
  158.  
  159.     // {{{ function rewind()
  160.     /**
  161.      * Sets the pointer for the linked list to the root node
  162.      *
  163.      * @return Structures_LinkedList_SingleNode root node in the linked list
  164.      */
  165.     public function rewind()
  166.     {
  167.         if ($this->root_node{
  168.             $this->current = $this->root_node;
  169.         else {
  170.             $this->current = null;
  171.         }
  172.         return $this->current;
  173.     }
  174.     // }}}
  175.  
  176.     // {{{ function end()
  177.     /**
  178.      * Sets the pointer for the linked list to the root node
  179.      *
  180.      * @return Structures_LinkedList_SingleNode root node in the linked list
  181.      */
  182.     public function end()
  183.     {
  184.         $this->current = $this->_getTailNode();
  185.         return $this->current;
  186.     }
  187.     // }}}
  188.  
  189.     // {{{ function key()
  190.     /**
  191.      * Stub for Iterator interface that simply returns the current node
  192.      *
  193.      * @return Structures_LinkedList_SingleNode current node in the linked list
  194.      */
  195.     public function key()
  196.     {
  197.         return $this->current;
  198.     }
  199.     // }}}
  200.  
  201.     // {{{ function valid()
  202.     /**
  203.      * Stub for Iterator interface that simply returns the current node
  204.      *
  205.      * @return Structures_LinkedList_SingleNode current node in the linked list
  206.      */
  207.     public function valid()
  208.     {
  209.         return $this->current();
  210.     }
  211.     // }}}
  212.  
  213.     // {{{ function next()
  214.     /**
  215.      * Sets the pointer for the linked list to the next node and
  216.      * returns that node
  217.      *
  218.      * @return Structures_LinkedList_SingleNode next node in the linked list
  219.      */
  220.     public function next()
  221.     {
  222.         if (!$this->current{
  223.             return false;
  224.         }
  225.         $this->current = $this->current()->next();
  226.         return $this->current;
  227.     }
  228.     // }}}
  229.  
  230.     // {{{ function previous()
  231.     /**
  232.      * Sets the pointer for the linked list to the previous node and
  233.      * returns that node
  234.      *
  235.      * @return Structures_LinkedList_SingleNode previous node in the linked list
  236.      */
  237.     public function previous()
  238.     {
  239.         if (!$this->current{
  240.             return false;
  241.         }
  242.         $this->current = $this->_getPreviousNode();
  243.         return $this->current;
  244.     }
  245.     // }}}
  246.  
  247.     // {{{ protected function _getTailNode()
  248.     /**
  249.      * Returns the tail node of the linked list.
  250.      *
  251.      * This is an expensive operation!
  252.      *
  253.      * @param Structures_LinkedList_SingleNode $new_node New node to append
  254.      * @return bool Success or failure
  255.      ***/
  256.     protected function _getTailNode()
  257.     {
  258.         $tail_node $this->root_node;
  259.         while (($y $tail_node->next()) !== false{
  260.             $tail_node $y;
  261.         }
  262.         return $tail_node;
  263.     }
  264.     // }}}
  265.  
  266.     // {{{ private function _getPreviousNode()
  267.     /**
  268.      * Returns the node prior to the current node in the linked list.
  269.      *
  270.      * This is an expensive operation for a singly linked list!
  271.      *
  272.      * @return Structures_LinkedList_SingleNode Previous node
  273.      ***/
  274.     private function _getPreviousNode($node = null)
  275.     {
  276.         if (!$node{
  277.             $node $this->current;
  278.         }
  279.         $prior_node $this->root_node;
  280.         while (($y $prior_node->next()) !== false{
  281.             if ($y == $node{
  282.                 return $prior_node;
  283.             }
  284.             $prior_node $y;
  285.         }
  286.         return null;
  287.     }
  288.     // }}}
  289.  
  290.     // {{{ function appendNode()
  291.     /**
  292.      * Adds a {@link Structures_LinkedList_SingleNode} object to the end of
  293.      * the linked list.
  294.      *
  295.      * @param Structures_LinkedList_SingleNode $new_node New node to append
  296.      * @return bool Success or failure
  297.      ***/
  298.     public function appendNode(Structures_LinkedList_SingleNode $new_node)
  299.     {
  300.         if (!$this->root_node{
  301.             $this->__construct($new_node);
  302.             return true;
  303.         }
  304.  
  305.         // This is just a special case of insertNode()
  306.         $this->insertNode($new_node$this->_getTailNode());
  307.  
  308.         return true;
  309.     }
  310.     // }}}
  311.  
  312.     // {{{ function insertNode()
  313.     /**
  314.      * Inserts a {@link Structures_LinkedList_SingleNode} object into the linked
  315.      * list, based on a reference node that already exists in the list.
  316.      *
  317.      * @param Structures_LinkedList_SingleNode $new_node New node to add to
  318.      *  the list
  319.      * @param Structures_LinkedList_SingleNode $existing_node Reference
  320.      *  position node
  321.      * @param bool $before Insert new node before or after the existing node
  322.      * @return bool Success or failure
  323.      ***/
  324.     public function insertNode(Structures_LinkedList_SingleNode $new_nodeStructures_LinkedList_SingleNode $existing_node$before = false)
  325.     {
  326.         if (!$this->root_node{
  327.             $this->__construct($new_node);
  328.             return true;
  329.         }
  330.  
  331.         // Now add the node according to the requested mode
  332.         switch ($before{
  333.  
  334.         case true:
  335.             if ($existing_node === $this->root_node{
  336.                 $this->root_node = $new_node;
  337.             }
  338.             $previous_node $this->_getPreviousNode($existing_node);
  339.             if ($previous_node{
  340.                 $previous_node->setNext($new_node);
  341.             }
  342.             $new_node->setNext($existing_node);
  343.  
  344.             break;
  345.  
  346.         case false:
  347.             $next_node $existing_node->next();
  348.             if ($next_node{
  349.                 $new_node->setNext($next_node);
  350.             }
  351.             $existing_node->setNext($new_node);
  352.  
  353.             break;
  354.  
  355.         }
  356.  
  357.         return true;
  358.     }
  359.     // }}}
  360.  
  361.     // {{{ function prependNode()
  362.     /**
  363.      * Adds a {@link Structures_LinkedList_SingleNode} object to the start
  364.      * of the linked list.
  365.      *
  366.      * @param Structures_LinkedList_SingleNode $new_node Node to prepend
  367.      *  to the list
  368.      * @return bool Success or failure
  369.      ***/
  370.     public function prependNode(Structures_LinkedList_SingleNode $new_node)
  371.     {
  372.         if (!$this->root_node{
  373.             $this->__construct($new_node);
  374.             return true;
  375.         }
  376.  
  377.         // This is just a special case of insertNode()
  378.         $this->insertNode($new_node$this->root_nodetrue);
  379.  
  380.         return true;
  381.     }
  382.     // }}}
  383.  
  384.     // {{{ function deleteNode()
  385.     /**
  386.      * Deletes a {@link Structures_LinkedList_SingleNode} from the list.
  387.      *
  388.      * @param Structures_LinkedList_SingleNode $node Node to delete.
  389.      */
  390.     public function deleteNode(Structures_LinkedList_SingleNode $node)
  391.     {
  392.         /* If this is the root node, and there are more nodes in the list,
  393.          * make the next node the new root node before deleting this node.
  394.          */
  395.         if ($node === $this->root_node{
  396.             $this->root_node = $node->next();
  397.         }
  398.         
  399.         /* If this is the current node, make the next node the current node.
  400.          *
  401.          * If that fails, null isn't such a bad place to be.
  402.          */
  403.         if ($node === $this->current{
  404.             if ($node->next()) {
  405.                 $this->current = $node->next();
  406.             else {
  407.                 $this->current = null;
  408.             }
  409.         }
  410.         $node->__destruct();
  411.     }
  412.     // }}}
  413.  
  414. }
  415. // }}}
  416.  
  417. // {{{ class Structures_LinkedList_SingleNode
  418. /**
  419.  * The Structures_LinkedList_SingleNode class represents a node in a
  420.  * {@link Structures_LinkedList_Single} linked list structure.
  421.  *
  422.  * @category   Structures
  423.  * @package    Structures_LinkedList_Single
  424.  * @author     Dan Scott <dscott@laurentian.ca>
  425.  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License, Version 2.0
  426.  * @link       http://pear.php.net/package/Structures_LinkedList_Single
  427.  */
  428.     // {{{ properties
  429.     /**
  430.      * Next node in the linked list
  431.      * @var Structures_LinkedList_SingleNode 
  432.      */
  433.     protected $next;
  434.     // }}}
  435.  
  436.     // {{{ Constructor: function __construct()
  437.     /**
  438.      * Structures_LinkedList_SingleNode constructor
  439.      */
  440.     public function __construct()
  441.     {
  442.         $this->next = null;
  443.     }
  444.     // }}}
  445.  
  446.     // {{{ Destructor: function __destruct()
  447.     /**
  448.      * Removes node from the list, adjusting the related nodes accordingly.
  449.      *
  450.      * This is a problem if the node is the root node for the list.
  451.      * At this point, however, we do not have access to the list itself. Hmm.
  452.      */
  453.     public function __destruct()
  454.     {
  455.     }
  456.     // }}}
  457.  
  458.     // {{{ function next()
  459.     /**
  460.      * Return the next node in the linked list
  461.      *
  462.      * @return Structures_LinkedList_SingleNode next node in the linked list
  463.      */
  464.     public function next()
  465.     {
  466.         if ($this->next{
  467.             return $this->next;
  468.         else {
  469.             return false;
  470.         }
  471.     }
  472.     // }}}
  473.  
  474.     // {{{ function previous()
  475.     /**
  476.      * Return the previous node in the linked list
  477.      *
  478.      * Stub method for Structures_LinkedList_DoubleNode to override.
  479.      *
  480.      * @return Structures_LinkedList_SingleNode previous node in the linked list
  481.      */
  482.     public function previous()
  483.     {
  484.         return false;
  485.     }
  486.     // }}}
  487.  
  488.     // {{{ function setNext()
  489.     /**
  490.      * Sets the pointer for the next node in the linked list to the
  491.      * specified node
  492.      *
  493.      * @param Structures_LinkedList_SingleNode $node new next node in
  494.      *  the linked list
  495.      * @return Structures_LinkedList_SingleNode new next node in the linked list
  496.      */
  497.     public function setNext(Structures_LinkedList_SingleNode $node = null)
  498.     {
  499.         $this->next = $node;
  500.         return $this->next;
  501.     }
  502.     // }}}
  503.  
  504.     // {{{ function setPrevious()
  505.     /**
  506.      * Sets the pointer for the next node in the linked list to the
  507.      * specified node
  508.      *
  509.      * Stub method for Structures_LinkedList_DoubleNode to override.
  510.      *
  511.      * @param Structures_LinkedList_SingleNode $node new next node in
  512.      *  the linked list
  513.      * @return Structures_LinkedList_SingleNode new next node in the linked list
  514.      */
  515.     public function setPrevious(Structures_LinkedList_SingleNode $node = null)
  516.     {
  517.         return false;
  518.     }
  519.     // }}}
  520. }
  521.  
  522. // }}}
  523.  
  524. ?>

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