| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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); |
| } |
| } |
| } |