blob: bf3e8a203ac3497464e32a46d7a5ffbbb069f9d1 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package mx.utils
{
/**
* Provides a generic doubly linked list implementation.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public class LinkedList
{
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
private var _head:LinkedListNode;
private var _tail:LinkedListNode;
private var _length:Number = 0;
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function LinkedList():void
{
_head = new LinkedListNode();
_tail = new LinkedListNode();
_head.next = _tail;
_tail.prev = _head;
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// head
//----------------------------------
/**
* Node representing head of the list.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function get head():LinkedListNode
{
return (_head.next == _tail) ? null : _head.next;
}
//----------------------------------
// length
//----------------------------------
/**
* Returns length of list.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function get length():Number
{
return _length;
}
//----------------------------------
// tail
//----------------------------------
/**
* Node representing tail of the list.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function get tail():LinkedListNode
{
return (_tail.prev == _head) ? null : _tail.prev;
}
//--------------------------------------------------------------------------
//
// Class methods
//
//--------------------------------------------------------------------------
/**
* Inserts new node after a previously existing node.
*
* @param value Value to insert. If the value is not a LinkedListNode
* one will be created.
*
* @param prev The previous node to insert relative to.
*
* @return The new node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function insertAfter(value:*, prev:LinkedListNode):LinkedListNode
{
var node:LinkedListNode = makeNode(value);
node.prev = prev;
node.next = prev.next;
node.prev.next = node;
node.next.prev = node;
_length++;
return node;
}
/**
* Inserts new node before a previously existing node.
*
* @param value Value to insert. If the value is not a LinkedListNode
* one will be created.
*
* @param prev The node to insert relative to.
*
* @return The new node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function insertBefore(value:*, next:LinkedListNode):LinkedListNode
{
var node:LinkedListNode = makeNode(value);
node.prev = next.prev;
node.next = next;
node.prev.next = node;
node.next.prev = node;
_length++;
return node;
}
/**
* Searches through all nodes for the given value.
*
* @param value The value to find.
*
* @return The node location.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function find(value:*):LinkedListNode
{
var cur:LinkedListNode = _head;
while (cur.value != value && cur != _tail)
cur = cur.next;
return (cur == _tail) ? null : cur;
}
/**
* Searches through all nodes for the given value and
* removes it from the list if found.
*
* @param value The value to find and remove.
* @return The removed node, null otherwise.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function remove(value:*):LinkedListNode
{
var node:LinkedListNode = getNode(value);
if (node)
{
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = node.prev = null;
_length--;
}
return node;
}
/**
* Push a new node to the tail of list.
*
* @param value The value to append.
* @return The newly appended node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function push(value:*):LinkedListNode
{
return insertAfter(value, _tail.prev);
}
/**
* Removes the node at the tail of the list.
*
* @return The removed node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function pop():LinkedListNode
{
return (_length == 0) ? null : remove(_tail.prev);
}
/**
* Push a new node to the head of list.
*
* @param value The value to append.
* @return The newly appended node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function unshift(value:*):LinkedListNode
{
return insertAfter(value, _head);
}
/**
* Removes the node at the head of the list.
*
* @return The removed node.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4.5
*/
public function shift():LinkedListNode
{
return (_length == 0) ? null : remove(_head.next);
}
/**
* @private
*/
protected function getNode(value:*):LinkedListNode
{
return (value is LinkedListNode) ? value : find(value);
}
/**
* @private
*/
protected function makeNode(value:*):LinkedListNode
{
return (value is LinkedListNode) ? value : new LinkedListNode(value);
}
}
}