Reverse a doubly linked list in O(1) time
2012-08-12 20:30
411 查看
#ifndef GYM_CLRS_V3_10_2_8_LINKED_LIST_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4 #define GYM_CLRS_V3_10_2_8_LINKED_LIST_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4 #include <assert.h> #include <stdint.h> #include <boost/call_traits.hpp> namespace pratique { namespace clrs_version { namespace detail { template <typename T> struct Node { T data; uintptr_t link; }; template <typename T> inline Node<T> * next( Node<T> * previous, Node<T> * node ) { uintptr_t n = reinterpret_cast<uintptr_t>( previous ) ^ node->link; return reinterpret_cast<Node<T>*>( n ); } template <typename T> inline Node<T> * previous( Node<T> * node, Node<T> * next ) { uintptr_t p = node->link ^ reinterpret_cast<uintptr_t>( next ); return reinterpret_cast<Node<T>*>( p ); } template <typename T> inline uintptr_t compound( Node<T> * previous, Node<T> * next ) { return reinterpret_cast<uintptr_t>( previous ) ^ reinterpret_cast<uintptr_t>( next ); } } template <typename T> class DoublyLinkedList { detail::Node<T> * m_head, * m_last; inline static detail::Node<T> * forward( detail::Node<T> ** previous, detail::Node<T> ** node ) { detail::Node<T> * tmp = *node; *node = detail::next( *previous, *node ); *previous = tmp; return tmp; } inline static detail::Node<T> * backward( detail::Node<T> ** node, detail::Node<T> ** next ) { detail::Node<T> * tmp = *node; *node = detail::previous( *node, *next ); *next = tmp; return tmp; } inline void free() { if ( m_head != NULL ) { detail::Node<T> * p = NULL, * n = m_head; do { delete forward( &p, &n ); } while ( n != m_head ); m_head = m_last = NULL; } } public: typedef size_t size_type; DoublyLinkedList() : m_head( NULL ), m_last( NULL ) {} ~DoublyLinkedList() { free(); } DoublyLinkedList( DoublyLinkedList<T> const & dll ) : m_head( NULL ), m_last( NULL ) { if ( dll.m_head != NULL ) { assert( dll.m_last != NULL ); detail::Node<T> * p = NULL, * n = dll.m_head, * tmp; detail::Node<T> * mya = NULL, * myp = NULL, * myn = NULL; ScopeGuard copy_destructor( [&]() { for ( detail::Node<T> * p = NULL, * n = m_head; n != myp; ) { delete forward( &p, &n ); } delete myp; } ); do { tmp = forward( &p, &n ); myn = new detail::Node<T>; myn->data = tmp->data; if ( m_head == NULL ) { m_head = myn; } if ( myp != NULL ) { myp->link = detail::compound( mya, myn ); } mya = myp; myp = myn; } while ( n != dll.m_head ); copy_destructor.dismiss(); myp->link = detail::compound( mya, m_head ); } } DoublyLinkedList<T> & operator=( DoublyLinkedList<T> const & dll ) { if ( this != &dll ) { DoublyLinkedList<T>( dll ).swap( *this ); } return *this; } void swap( DoublyLinkedList<T> & dll ) { using std::swap; swap( m_head, dll.m_head ); swap( m_last, dll.m_last ); } bool operator==( DoublyLinkedList<T> const & dll ) const { bool equals = false; detail::Node<T> * p = NULL, * n = dll.m_head; detail::Node<T> * myp = NULL, * myn = m_head; if ( n != NULL && myn != NULL ) { do { if ( n->data == myn->data ) { forward( &p, &n ); forward( &myp, &myn ); } else { break; } } while ( n != dll.m_head && myn != m_head ); equals = ( n == dll.m_head && myn == m_head ); } else { equals = true; } return equals; } inline bool operator!=( DoublyLinkedList<T> const & dll ) const { return !( operator==( dll ) ); } inline bool empty() const { return ( m_head == NULL ); } size_type size() const { size_t count = 0; if ( m_head != NULL ) { detail::Node<T> * previous = NULL, * current = m_head, * tmp; do { ++count; tmp = current; current = next( previous, current ); previous = tmp; } while ( current != m_head ); } return count; } void push_back( typename boost::call_traits<T>::param_type v ) { detail::Node<T> * p = new detail::Node<T>; p->data = v; if ( m_head != NULL ) { detail::Node<T> * previous = detail::previous( m_last, m_head ); m_last->link = detail::compound( previous, p ); p->link = detail::compound( m_last, m_head ); } else { detail::Node<T> * previous = NULL; m_head = p; m_head->link = detail::compound( previous, p ); } m_last = p; } void pop_back() { if ( m_head != NULL ) { detail::Node<T> * previous = detail::previous( m_last, m_head ); if ( previous != NULL ) { detail::Node<T> * ancestor = detail::previous( previous, m_last ); delete m_last; previous->link = detail::compound( ancestor, m_head ); m_last = previous; } else { assert( m_last == m_head ); delete m_head; m_last = m_head = NULL; } } } void push_front( typename boost::call_traits<T>::param_type v ) { detail::Node<T> * null_previous = NULL; detail::Node<T> * p = new detail::Node<T>; p->data = v; if ( m_head != NULL ) { detail::Node<T> * previous = detail::previous( m_last 4000 , m_head ); detail::Node<T> * next = detail::next( null_previous, m_head ); p->link = detail::compound( null_previous, m_head ); if ( previous != NULL ) { m_last->link = detail::compound( previous, p ); m_head->link = detail::compound( p, next ); } else { m_head->link = detail::compound( p, p ); m_last = m_head; } } else { p->link = detail::compound( null_previous, p ); m_last = p; } m_head = p; } void pop_front() { if ( m_head != NULL ) { detail::Node<T> * null_previous = NULL; detail::Node<T> * previous = detail::previous( m_last, m_head ); if ( previous != NULL ) { detail::Node<T> * next = detail::next( null_previous, m_head ); if ( next != m_last ) { detail::Node<T> * third = detail::next( m_head, next ); m_last->link = detail::compound( previous, next ); next->link = detail::compound( null_previous, third ); } else { m_last->link = detail::compound( null_previous, m_last ); } delete m_head; m_head = next; } else { delete m_head; m_head = m_last = NULL; } } } void reverse() { if ( m_head != m_last ) { detail::Node<T> * null_previous = NULL; detail::Node<T> * previous = detail::previous( m_last, m_head ); detail::Node<T> * next = detail::next( null_previous, m_head ); m_last->link = detail::compound( null_previous, previous ); m_head->link = detail::compound( m_last, next ); std::swap( m_last, m_head ); } } T const & front() const { assert( !empty() ); return m_head->data; } T const & back() const { assert( !empty() ); return m_last->data; } class Iterator { friend class DoublyLinkedList<T>; detail::Node<T> * m_previous, * m_current, * m_last; Iterator( DoublyLinkedList<T> const * dll ) : m_previous( NULL ), m_current( dll->m_head ), m_last( dll->m_last ) {} public: Iterator() : m_previous( NULL ), m_current( NULL ), m_last( NULL ) {} typedef std::bidirectional_iterator_tag iterator_category; typedef T value_type; typedef detail::Node<T> * pointer; typedef ptrdiff_t difference_type; typedef T const & reference; reference operator*() const { return m_current->data; } Iterator & operator++() { DoublyLinkedList<T>::forward( &m_previous, &m_current ); return (*this); } Iterator operator++(int) { Iterator tmp( *this ); ++*this; return tmp; } Iterator & operator--() { DoublyLinkedList<T>::backward( &m_previous, &m_current ); return (*this); } Iterator operator--(int) { Iterator tmp( *this ); --*this; return tmp; } bool operator==( const Iterator & i ) const { return ( m_current == i.m_current && m_previous == i.m_previous ); } bool operator!=( const Iterator& i ) const { return ( m_current != i.m_current || m_previous != i.m_previous ); } }; typedef Iterator iterator; iterator begin() const { return Iterator( this ); } iterator end() const { Iterator i; i.m_previous = this->m_last; i.m_current = this->m_head; i.m_last = this->m_last; return i; } }; } } #endif //GYM_CLRS_V3_10_2_8_LINKED_LIST_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4
The testing code is:
typedef pratique::clrs_version::DoublyLinkedList<int> mydll; void must_be_equals( mydll const & l, mydll const & r ) { if ( l != r ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); } } void clrs_list_test() { { mydll dll; { mydll copy( dll ); must_be_equals( dll, copy ); } dll.push_back( 1 ); dll.pop_back(); { mydll copy( dll ); must_be_equals( dll, copy ); } } { mydll dll; dll.push_back( 1 ); { mydll copy( dll ); must_be_equals( dll, copy ); } dll.push_back( 2 ); dll.pop_back(); { mydll copy( dll ); must_be_equals( dll, copy ); } } { mydll dll; const int limits = 128; int to_be_compared[ limits ]; for ( int i = 0; i < limits; ++i ) { to_be_compared[i] = i; } for ( int i = 0; i < limits; ++i ) { dll.push_back( i ); if ( !std::equal( dll.begin(), dll.end(), std::begin( to_be_compared ) ) ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } while ( !dll.empty() ) { dll.pop_back(); } for ( int i = 0; i < limits; ++i ) { dll.push_back( i ); if ( !std::equal( dll.begin(), dll.end(), std::begin( to_be_compared ) ) ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } dll.reverse(); int count = 0; std::vector<int> result; while ( !dll.empty() ) { ++count; result.push_back( dll.back() ); dll.pop_back(); } for ( int i = 0; i < limits; ++i ) { if ( result[i] != i ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } mydll copy( dll ); must_be_equals( dll, copy ); } { mydll dll; dll.push_front( 1 ); dll.pop_front(); { mydll copy( dll ); must_be_equals( dll, copy ); } } { mydll dll; dll.push_front( 1 ); { mydll copy( dll ); must_be_equals( dll, copy ); } dll.push_front( 2 ); dll.pop_front(); { mydll copy( dll ); must_be_equals( dll, copy ); } } { mydll dll; const int limits = 128; int to_be_compared[ limits ]; for ( int i = 0; i < limits; ++i ) { to_be_compared[i] = i; } for ( int i = limits - 1; i >= 0; --i ) { dll.push_front( i ); if ( !std::equal( dll.begin(), dll.end(), std::begin( to_be_compared ) + i ) ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } while ( !dll.empty() ) { dll.pop_back(); } for ( int i = limits - 1; i >= 0; --i ) { dll.push_front( i ); if ( !std::equal( dll.begin(), dll.end(), std::begin( to_be_compared ) + i ) ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } dll.reverse(); int count = 0; std::vector<int> result; while ( !dll.empty() ) { ++count; result.push_back( dll.back() ); dll.pop_back(); } for ( int i = 0; i < limits; ++i ) { if ( result[i] != i ) { fprintf( stderr, "Bad implementation for the problem CRLS 10-2-8\n" ); DebugBreak(); break; } } mydll copy( dll ); must_be_equals( dll, copy ); } }
相关文章推荐
- 逆置双向链表 Reverse a doubly linked list
- LeetCode 25 Reverse Nodes in k-Group(在K组链表中反转结点)(Linked List)(*)
- [TS] Implement a doubly linked list in TypeScript
- Reverse Words in a String,Maximum Product Subarray,Reverse Linked List II
- Sort a linked list in O(n log n) time using constant space complexity.
- leetcode Sort List (Sort a linked list in O(n log n) time using constant space complexity)
- 两两反转单向链表 (reverse a singly linked list in pair ) [#22]
- LeetCode[Linked List]: Reverse Nodes in k-Group
- Sort a linked list in O(n log n) time using constant space complexity.
- [Linked List]Reverse Nodes in k-Group
- leetcode_Sort a linked list in O(n log n) time using constant space complexity.
- FW:Reverse a Singly Linked List Recursively in Java
- Sort a linked list in O(n log n) time using constant space complexity
- Data Structure Linked List: Reverse a Linked List in groups of given size
- reverse linkedlist in k group
- leetcode Sort a linked list in O(n log n) time using constant space complexity.
- Sort a linked list in O(n log n) time using constant space complexity.
- 【Hackerrank】Reverse a doubly linked list
- Ch2-4:add reverse 1 digit format number in linked list
- LeetCode解题报告—— Linked List Cycle II & Reverse Words in a String & Fraction to Recurring Decimal