分享
 
 
 

C++ young 程序库——y_slist.hpp

王朝c/c++·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

文件位置: young/y_slist.hpp

/*

The young Library

Copyright (c) 2005 by 杨桓

Permission to use, copy, modify, distribute and sell this software for any

purpose is hereby granted without fee, provided that the above copyright

notice appear in all copies and that both that copyright notice and this

permission notice appear in supporting documentation.

The author make no representations about the suitability of this software

for any purpose. It is provided "as is" without express or implied warranty.

*/

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

#ifndef __MACRO_CPLUSPLUS_YOUNG_LIBRARY_SLIST_HEADER_FILE__

#define __MACRO_CPLUSPLUS_YOUNG_LIBRARY_SLIST_HEADER_FILE__

//-----------------------------------------------------------------------------

#include "y_allocator.hpp"

#include "y_construct.hpp"

#include "y_exception.hpp"

#include "algorithm/y_algorithm_base.hpp"

#include "algorithm/y_algorithm_compare.hpp"

//-----------------------------------------------------------------------------

__MACRO_CPLUSPLUS_YOUNG_LIBRARY_BEGIN_NAMESPACE__

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

static const int slist_sort_array = 32;

struct slist_node_base

{

slist_node_base* next;

};

template< typename Value >

struct slist_node : public slist_node_base

{

Value data;

};

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

def_size_t slist_size( const slist_node_base* begin,

const slist_node_base* end )

{

def_size_t n = 0;

while( begin != end )

{

begin = begin->next;

++n;

}

return n;

}

slist_node_base* slist_prev( slist_node_base* begin,

const slist_node_base* node )

{

if( begin != node )

{

while( begin && begin->next != node )

begin = begin->next;

}

return begin;

}

inline slist_node_base* slist_make_link( slist_node_base* prev_node,

slist_node_base* new_node )

{

new_node->next = prev_node->next;

prev_node->next = new_node;

return new_node;

}

inline slist_node_base* slist_erase_after_node( slist_node_base* position )

{

slist_node_base* erase_node = position->next;

slist_node_base* next_node = erase_node->next;

position->next = next_node;

return next_node;

}

void slist_splice_after( slist_node_base* position,

slist_node_base* before_first,

slist_node_base* before_last )

{

if( position != before_first && position != before_last )

{

slist_node_base* first = before_first->next;

slist_node_base* pos_after = position->next;

before_first->next = before_last->next;

position->next = first;

before_last->next = pos_after;

}

}

slist_node_base* slist_reverse( slist_node_base* first )

{

slist_node_base* result = first;

slist_node_base* next;

first = first->next;

result->next = NULL_POINTER;

while( first )

{

next = first->next;

first->next = result;

result = first;

first = next;

}

return result;

}

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

template< typename T, typename Ref, typename Ptr, typename Alloc >

class slist_iterator;

template< typename T, typename Allocator >

class slist;

template< typename T, typename Ref, typename Ptr, typename Alloc >

class slist_iterator

{

public:

typedef forward_iterator_tag iterator_category;

typedef def_size_t size_type;

typedef def_ptrdiff_t difference_type;

typedef T value_type;

typedef Ref reference;

typedef Ptr pointer;

typedef slist_iterator<T, Ref, Ptr, Alloc> self;

typedef slist_iterator<T, T&, T*, Alloc> iterator;

typedef slist_iterator<T, const T&, const T*, Alloc> const_iterator;

private:

typedef slist_node_base* base_ptr;

typedef slist_node<T>* node_ptr;

typedef typename primal_type<Ref>::contrary_const_ref Ref_t;

typedef typename primal_type<Ptr>::contrary_const_ptr Ptr_t;

friend class slist<T, Alloc>;

friend class slist_iterator<T, Ref_t, Ptr_t, Alloc>;

friend iterator const_iter_cast <> ( const const_iterator& );

base_ptr node;

public:

slist_iterator() : node(NULL_POINTER) {}

slist_iterator( base_ptr p ) : node(p) {}

slist_iterator( node_ptr p ) : node(p) {}

slist_iterator( const iterator& x ) : node(x.node) {}

self& operator=( def_nullptr_t n )

{

if( n == NULL_POINTER )

node = NULL_POINTER;

return *this;

}

bool operator!() const { return !node; }

bool operator==( const self& rhs ) const { return node == rhs.node; }

bool operator!=( const self& rhs ) const { return node != rhs.node; }

reference operator*() const

{ return static_cast<node_ptr>(node)->data; }

pointer operator->() const

{ return &( operator*() ); }

self& operator++()

{ node = node->next; return *this; }

self operator++(int)

{ self old = *this; node = node->next; return old; }

self& operator+=( size_type n )

{ increment_n(n); return *this; }

self next() { return node->next; }

private:

void increment_n( size_type n )

{

for( ; n > 0; --n )

node = node->next;

}

}; //end iterator

template< typename T, typename Ref, typename Ptr, typename Alloc >

inline slist_iterator<T, Ref, Ptr, Alloc>

operator+( const slist_iterator<T, Ref, Ptr, Alloc>& lhs, def_size_t n )

{

slist_iterator<T, Ref, Ptr, Alloc> temp( lhs );

return ( temp += n );

}

template< typename T, typename Ref, typename Ptr, typename Alloc >

inline slist_iterator<T, Ref, Ptr, Alloc>

operator+( def_size_t n, const slist_iterator<T, Ref, Ptr, Alloc>& rhs )

{

slist_iterator<T, Ref, Ptr, Alloc> temp( rhs );

return ( temp += n );

}

template< typename T, typename Alloc >

inline slist_iterator<T, T&, T*, Alloc>

const_iter_cast( const slist_iterator<T, const T&, const T*, Alloc>& citer )

{

return slist_iterator<T, T&, T*, Alloc>( citer.node );

}

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

template< typename T, typename Allocator = allocator< slist_node<T> > >

class slist

{

public:

typedef slist<T, Allocator> self;

typedef Allocator allocator_type;

typedef T value_type;

typedef value_type& reference;

typedef const value_type& const_reference;

typedef value_type* pointer;

typedef const value_type* const_pointer;

typedef def_size_t size_type;

typedef def_ptrdiff_t difference_type;

typedef slist_iterator<T, T&, T*, Allocator> iterator;

typedef slist_iterator<T, const T&, const T*, Allocator> const_iterator;

protected:

typedef slist_node_base base_node_type;

typedef slist_node_base* base_ptr;

typedef slist_node<T> node_type;

typedef slist_node<T>* node_ptr;

base_node_type m_header;

allocator_type m_alloc;

public:

slist() { init_header(); }

explicit slist( size_type size )

{ fill_init( size, value_type() ); }

slist( size_type size, const_reference value )

{ fill_init( size, value ); }

slist( int size, const_reference value )

{ fill_init( static_cast<size_type>(size), value ); }

slist( long size, const_reference value )

{ fill_init( static_cast<size_type>(size), value ); }

template< typename InputIterator >

slist( InputIterator first, InputIterator last )

{

init_header();

try

{

insert_after( header(), first, last );

}

catch(...)

{

clear();

throw;

}

}

slist( const self& rhs )

{

init_header();

try

{

insert_after( header(), rhs.begin(), rhs.end() );

}

catch(...)

{

clear();

throw;

}

}

self& operator=( const self& rhs )

{

if( this != &rhs )

assign( rhs.begin(), rhs.end() );

return *this;

}

~slist() { clear(); }

iterator begin() { return m_header.next; }

iterator end() { return (node_ptr)NULL_POINTER; }

const_iterator begin() const { return m_header.next; }

const_iterator end() const { return (node_ptr)NULL_POINTER; }

reference front() { return *begin(); }

const_reference front() const { return *begin(); }

bool empty() const { return ( m_header.next == NULL_POINTER ); }

size_type max_size() const { return size_t_max; }

void clear() { erase_after( header(), end() ); }

reference at( size_type index );

const_reference at( size_type index ) const;

reference operator[]( size_type index )

{

iterator result = begin();

return *( result += index );

}

const_reference operator[]( size_type index ) const

{

const_iterator result = begin();

return *( result += index );

}

iterator previous( iterator position )

{ return slist_prev( &m_header, position.node ); }

const_iterator previous( const_iterator position ) const

{ return slist_prev( &m_header, position.node ); }

size_type size() const

{

return slist_size( m_header.next, NULL_POINTER );

}

void push_front( const_reference value )

{

slist_make_link( &m_header, create_node(value) );

}

void pop_front()

{

base_ptr x = m_header.next;

m_header.next = x->next;

destroy_node( static_cast<node_ptr>(x) );

}

void swap( self& rhs )

{

if( this != &rhs )

{

data_swap( m_header, rhs.m_header );

data_swap( m_alloc, rhs.m_alloc );

}

}

void reverse()

{

if( !empty() && m_header.next->next )

m_header.next = slist_reverse( m_header.next );

}

void resize( size_type new_size, const_reference value = value_type() );

void assign( size_type new_size, const_reference value = value_type() );

void assign( int new_size, const_reference value = value_type() )

{ assign( static_cast<size_type>(new_size), value ); }

void assign( long new_size, const_reference value = value_type() )

{ assign( static_cast<size_type>(new_size), value ); }

template< typename InputIterator >

void assign( InputIterator first, InputIterator last );

void insert_after( iterator position, size_type count,

const_reference value );

iterator insert_after( iterator position,

const_reference value = value_type() )

{ return slist_make_link( position.node, create_node(value) ); }

void insert_after( iterator position, int count, const_reference value )

{ insert_after( position, static_cast<size_type>(count), value ); }

void insert_after( iterator position, long count, const_reference value )

{ insert_after( position, static_cast<size_type>(count), value ); }

template< typename InputIterator >

void insert_after( iterator position,

InputIterator first, InputIterator last );

void insert( iterator position, size_type count, const_reference value )

{ insert_after( previous(position), count, value ); }

void insert( iterator position, int count, const_reference value )

{ insert( position, static_cast<size_type>(count), value ); }

void insert( iterator position, long count, const_reference value )

{ insert( position, static_cast<size_type>(count), value ); }

iterator insert( iterator position, const_reference value = value_type() )

{ return insert_after( previous(position), value ); }

template< typename InputIterator >

void insert( iterator position, InputIterator first, InputIterator last )

{ insert_after( previous(position), first, last ); }

iterator erase_after( iterator position );

iterator erase_after( iterator before_first, iterator last );

iterator erase( iterator position )

{ return erase_after( slist_prev(&m_header, position.node) ); }

iterator erase( iterator first, iterator last )

{ return erase_after( slist_prev(&m_header, first.node), last.node ); }

void splice_after( iterator position, iterator before_first,

iterator before_last )

{

if( before_first != before_last )

slist_splice_after( position.node, before_first.node,

before_last.node );

}

void splice_after( iterator position, iterator prev )

{

slist_splice_after( position.node, prev.node, prev.node->next );

}

void splice( iterator position, self& rhs )

{

if( !rhs.empty() )

slist_splice_after( slist_prev( &m_header, position.node ),

&rhs.m_header,

slist_prev( &rhs.m_header, &rhs.m_header ) );

}

// [ first, last ) 必须在 rhs 范围之内

void splice( iterator position, self& rhs, iterator first, iterator last )

{

if( first != last )

slist_splice_after( slist_prev( &m_header, position.node ),

slist_prev( &rhs.m_header, first.node ),

slist_prev( first.node, last.node ) );

}

//new_node 必须在 rhs 范围之内

void splice( iterator position, self& rhs, iterator new_node )

{

if( position != new_node )

slist_splice_after( slist_prev( &m_header, position.node ),

slist_prev( &rhs.m_header, new_node.node ),

new_node.node );

}

void remove( const_reference value );

void merge( self& rhs );

void unique();

void sort();

template< typename Predicate >

void remove_if( Predicate pred );

template< typename StrictWeakOrdering >

void merge( self& rhs, StrictWeakOrdering comp );

template< typename BinaryPredicate >

void unique( BinaryPredicate bin_pred );

template< typename StrictWeakOrdering >

void sort( StrictWeakOrdering comp );

protected:

void init_header() { m_header.next = NULL_POINTER; }

iterator header() { return &m_header; }

node_ptr create_node( const T& x )

{

node_ptr ptr = m_alloc.allocate( 1 );

try

{

construct( &(ptr->data), x );

}

catch(...)

{

m_alloc.deallocate( ptr, 1 );

throw;

}

ptr->next = NULL_POINTER;

return ptr;

}

void destroy_node( node_ptr ptr )

{

destroy( &(ptr->data) );

m_alloc.deallocate( ptr, 1 );

}

void fill_init( size_type n, const_reference value )

{

init_header();

try

{

insert_after( header(), n, value );

}

catch(...)

{

clear();

throw;

}

}

}; //end class

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

typename slist<T, Allocator>::reference

slist<T, Allocator>::at( size_type index )

{

if( empty() )

throw_out_of_range( "slist::at()" );

iterator result = begin();

iterator finish = end();

for( ; index > 0; --index,++result )

{

if( result == finish )

throw_out_of_range( "slist::at()" );

}

return *result;

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

typename slist<T, Allocator>::const_reference

slist<T, Allocator>::at( size_type index ) const

{

if( empty() )

throw_out_of_range( "slist::at()" );

const_iterator result = begin();

const_iterator finish = end();

for( ; index > 0; --index,++result )

{

if( result == finish )

throw_out_of_range( "slist::at()" );

}

return *result;

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::insert_after( iterator position,

size_type count,

const_reference value )

{

base_ptr pos = position.node;

for( ; count > 0; --count )

pos = slist_make_link( pos, create_node(value) );

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename InputIterator >

void slist<T, Allocator>::insert_after( iterator position,

InputIterator first,

InputIterator last )

{

base_ptr pos = position.node;

while( first != last )

{

pos = slist_make_link( pos, create_node(*first) );

++first;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

typename slist<T, Allocator>::iterator

slist<T, Allocator>::erase_after( iterator position )

{

if( position == end() )

return position;

base_ptr erase_node = position.node->next;

base_ptr next_node = slist_erase_after_node( position.node );

destroy_node( static_cast<node_ptr>(erase_node) );

return next_node;

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

typename slist<T, Allocator>::iterator

slist<T, Allocator>::erase_after( iterator before_first, iterator last )

{

base_ptr curr = before_first.node->next;

base_ptr temp;

while( curr != last.node )

{

temp = curr;

curr = curr->next;

destroy_node( static_cast<node_ptr>(temp) );

}

before_first.node->next = last.node;

return last;

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::resize( size_type new_size, const_reference value )

{

base_ptr curr = &m_header;

while( curr->next && new_size > 0 )

{

--new_size;

curr = curr->next;

}

if( new_size == 0 )

erase_after( curr, end() );

else

insert_after( curr, new_size, value );

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::assign( size_type new_size, const_reference value )

{

if( new_size < 1 )

{

clear();

return;

}

base_ptr curr = &m_header;

while( curr->next && new_size > 0 )

{

curr = curr->next;

static_cast<node_ptr>(curr)->data = value;

--new_size;

}

if( curr->next )

erase_after( iterator(curr), end() );

else

insert_after( iterator(curr), new_size, value );

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename InputIterator >

void slist<T, Allocator>::assign( InputIterator first, InputIterator last )

{

if( first == last )

{

clear();

return;

}

base_ptr curr = &m_header;

while( curr->next && first != last )

{

curr = curr->next;

static_cast<node_ptr>(curr)->data = *first;

++first;

}

if( curr->next )

erase_after( iterator(curr), end() );

else

insert_after( iterator(curr), first, last );

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::remove( const_reference value )

{

iterator first = header();

iterator last = end();

iterator temp;

while( first != last )

{

temp = first;

++temp;

if( *temp == value )

erase_after( first );

else

++first;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename Predicate >

void slist<T, Allocator>::remove_if( Predicate pred )

{

iterator first = header();

iterator last = end();

iterator temp;

while( first != last )

{

temp = first;

++temp;

if( pred(*temp) )

erase_after( first );

else

++first;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::unique()

{

if( empty() || m_header.next->next == NULL_POINTER )

return;

iterator first = begin();

iterator last = end();

iterator temp;

while( first != last )

{

temp = first;

++temp;

if( *temp == *first )

erase_after( first );

else

++first;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename BinaryPredicate >

void slist<T, Allocator>::unique( BinaryPredicate bin_pred )

{

if( empty() || m_header.next->next == NULL_POINTER )

return;

iterator first = begin();

iterator last = end();

iterator temp;

while( first != last )

{

temp = first;

++temp;

if( bin_pred(*temp, *first) )

erase_after( first );

else

++first;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::merge( self& rhs )

{

if( rhs.empty() )

return;

iterator curr = header();

iterator next;

while( curr.node->next && rhs.m_header.next )

{

next = curr;

++next;

if( *(rhs.begin()) < *next )

splice_after( curr, rhs.header(), rhs.begin() );

++curr;

}

if( rhs.m_header.next )

{

curr.node->next = rhs.m_header.next;

rhs.m_header.next = NULL_POINTER;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename StrictWeakOrdering >

void slist<T, Allocator>::merge( self& rhs, StrictWeakOrdering comp )

{

if( rhs.empty() )

return;

iterator curr = header();

iterator next;

while( curr.node->next && rhs.m_header.next )

{

next = curr;

++next;

if( comp( *(rhs.begin()), *next ) )

splice_after( curr, rhs.header(), rhs.begin() );

++curr;

}

if( rhs.m_header.next )

{

curr.node->next = rhs.m_header.next;

rhs.m_header.next = NULL_POINTER;

}

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

void slist<T, Allocator>::sort()

{

if( empty() || m_header.next->next == NULL_POINTER )

return;

self carry;

self result[ slist_sort_array ];

size_type fill = 0;

while( !empty() )

{

carry.splice_after( carry.header(), header(), begin() );

size_type i = 0;

while( i < fill && !result[i].empty() )

{

result[i].merge( carry );

carry.swap( result[i] );

++i;

}

carry.swap( result[i] );

if( i == fill )

++fill;

}

for( size_type j = 1; j < fill; ++j )

result[j].merge( result[j - 1] );

swap( result[fill - 1] );

}

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

template< typename StrictWeakOrdering >

void slist<T, Allocator>::sort( StrictWeakOrdering comp )

{

if( empty() || m_header.next->next == NULL_POINTER )

return;

self carry;

self result[ slist_sort_array ];

size_type fill = 0;

while( !empty() )

{

carry.splice_after( carry.header(), header(), begin() );

size_type i = 0;

while( i < fill && !result[i].empty() )

{

result[i].merge( carry, comp );

carry.swap( result[i] );

++i;

}

carry.swap( result[i] );

if( i == fill )

++fill;

}

for( size_type j = 1; j < fill; ++j )

result[j].merge( result[j - 1], comp );

swap( result[fill - 1] );

}

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

template< typename T, typename Allocator >

inline void swap( slist<T,Allocator>& lhs, slist<T,Allocator>& rhs )

{

lhs.swap( rhs );

}

template< typename T, typename Allocator >

inline bool operator==( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

if( lhs.previous( lhs.begin() ) == rhs.previous( rhs.begin() ) )

return true;

return matching( lhs.begin(), lhs.end(), rhs.begin(), rhs.end() );

}

template< typename T, typename Allocator >

inline bool operator!=( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

return !( lhs == rhs );

}

template< typename T, typename Allocator >

inline bool operator<( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

if( lhs.previous( lhs.begin() ) == rhs.previous( rhs.begin() ) )

return false;

return lexicographical_compare( lhs.begin(), lhs.end(),

rhs.begin(), rhs.end() );

}

template< typename T, typename Allocator >

inline bool operator>( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

return ( rhs < lhs );

}

template< typename T, typename Allocator >

inline bool operator<=( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

return !( rhs < lhs );

}

template< typename T, typename Allocator >

inline bool operator>=( const slist<T, Allocator>& lhs,

const slist<T, Allocator>& rhs )

{

return !( lhs < rhs );

}

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

__MACRO_CPLUSPLUS_YOUNG_LIBRARY_END_NAMESPACE__

#endif

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有