青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

雪竹的天空

theorix

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  34 隨筆 :: 0 文章 :: 20 評論 :: 0 Trackbacks

1 數據結構:hash_map原理

這是一節讓你深入理解hash_map的介紹,如果你只是想囫圇吞棗,不想理解其原理,你倒是可以略過這一節,但我還是建議你看看,多了解一些沒有壞處。

hash_map基于hash table(哈希表)。 哈希表最大的優點,就是把數據的存儲和查找消耗的時間大大降低,幾乎可以看成是常數時間;而代價僅僅是消耗比較多的內存。然而在當前可利用內存越來越多的情況下,用空間換時間的做法是值得的。另外,編碼比較容易也是它的特點之一。

其基本原理是:使用一個下標范圍比較大的數組來存儲元素。可以設計一個函數(哈希函數,也叫做散列函數),使得每個元素的關鍵字都與一個函數值(即數組下標,hash值)相對應,于是用這個數組單元來存儲這個元素;也可以簡單的理解為,按照關鍵字為每一個元素“分類”,然后將這個元素存儲在相應“類”所對應的地方,稱為桶。

但是,不能夠保證每個元素的關鍵字與函數值是一一對應的,因此極有可能出現對于不同的元素,卻計算出了相同的函數值,這樣就產生了“沖突”,換句話說,就是把不同的元素分在了相同的“類”之中。 總的來說,“直接定址”與“解決沖突”是哈希表的兩大特點。

hash_map,首先分配一大片內存,形成許多桶。是利用hash函數,對key進行映射到不同區域(桶)進行保存。其插入過程是:

  1. 得到key
  2. 通過hash函數得到hash值
  3. 得到桶號(一般都為hash值對桶數求模)
  4. 存放key和value在桶內。
其取值過程是:
  1. 得到key
  2. 通過hash函數得到hash值
  3. 得到桶號(一般都為hash值對桶數求模)
  4. 比較桶的內部元素是否與key相等,若都不相等,則沒有找到。
  5. 取出相等的記錄的value。
hash_map中直接地址用hash函數生成,解決沖突,用比較函數解決。這里可以看出,如果每個桶內部只有一個元素,那么查找的時候只有一次比較。當許多桶內沒有值時,許多查詢就會更快了(指查不到的時候).

由此可見,要實現哈希表, 和用戶相關的是:hash函數和比較函數。這兩個參數剛好是我們在使用hash_map時需要指定的參數。

2 hash_map 使用

2.1 一個簡單實例

不要著急如何把"岳不群"用hash_map表示,我們先看一個簡單的例子:隨機給你一個ID號和ID號相應的信息,ID號的范圍是1~2的31次方。如何快速保存查找。
#include <hash_map>
                                    #include <string>
                                    using namespace std;
                                    int main(){
                                    hash_map<int, string> mymap;
                                    mymap[9527]="唐伯虎點秋香";
                                    mymap[1000000]="百萬富翁的生活";
                                    mymap[10000]="白領的工資底線";
                                    ...
                                    if(mymap.find(10000) != mymap.end()){
                                    ...
                                    }

                                    
夠簡單,和map使用方法一樣。這時你或許會問?hash函數和比較函數呢?不是要指定么?你說對了,但是在你沒有指定hash函數和比較函數的時候,你會有一個缺省的函數,看看hash_map的聲明,你會更加明白。下面是SGI STL的聲明:
template <class _Key, class _Tp, class _HashFcn = hash<_Key>,
                                    class _EqualKey = equal_to<_Key>,
                                    class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
                                    class hash_map
                                    {
                                    ...
                                    }

                                    
也就是說,在上例中,有以下等同關系:
...
                                    hash_map<int, string> mymap;
                                    //等同于:
                                    hash_map<int, string, hash<int>, equal_to<int> > mymap;

                                    
Alloc我們就不要取關注太多了(希望深入了解Allocator的朋友可以參看標準庫 STL :Allocator能做什么)

2.2 hash_map 的hash函數

hash< int>到底是什么樣子?看看源碼:
struct hash<int> {
                                    size_t operator()(int __x) const { return __x; }
                                    };

                                    
原來是個函數對象。在SGI STL中,提供了以下hash函數:
struct hash<char*>
                                    struct hash<const char*>
                                    struct hash<char>
                                    struct hash<unsigned char>
                                    struct hash<signed char>
                                    struct hash<short>
                                    struct hash<unsigned short>
                                    struct hash<int>
                                    struct hash<unsigned int>
                                    struct hash<long>
                                    struct hash<unsigned long> 

                                    
也就是說,如果你的key使用的是以上類型中的一種,你都可以使用缺省的hash函數。當然你自己也可以定義自己的hash函數。對于自定義變量,你只能如此,例如對于string,就必須自定義hash函數。例如:
struct str_hash{
                                    size_t operator()(const string& str) const
                                    {
                                    unsigned long __h = 0;
                                    for (size_t i = 0 ; i < str.size() ; i ++)
                                    __h = 5*__h + str[i];
                                    return size_t(__h);
                                    }
                                    };
                                    //如果你希望利用系統定義的字符串hash函數,你可以這樣寫:
                                    struct str_hash{
                                    size_t operator()(const string& str) const
                                    {
                                    return return __stl_hash_string(str.c_str());
                                    }
                                    };

                                    
在聲明自己的哈希函數時要注意以下幾點:
  1. 使用struct,然后重載operator().
  2. 返回是size_t
  3. 參數是你要hash的key的類型。
  4. 函數是const類型的。
如果這些比較難記,最簡單的方法就是照貓畫虎,找一個函數改改就是了。

現在可以對開頭的"岳不群"進行哈希化了 smile . 直接替換成下面的聲明即可:

map<string, string> namemap;
                                    //改為:
                                    hash_map<string, string, str_hash> namemap;

                                    
其他用法都不用邊。當然不要忘了吧str_hash的聲明以及頭文件改為hash_map。

你或許會問:比較函數呢?別著急,這里就開始介紹hash_map中的比較函數。

2.3 hash_map 的比較函數

在map中的比較函數,需要提供less函數。如果沒有提供,缺省的也是less< Key> 。在hash_map中,要比較桶內的數據和key是否相等,因此需要的是是否等于的函數:equal_to< Key> 。先看看equal_to的源碼:
//本代碼可以從SGI STL
                                    //先看看binary_function 函數聲明,其實只是定義一些類型而已。
                                    template <class _Arg1, class _Arg2, class _Result>
                                    struct binary_function {
                                    typedef _Arg1 first_argument_type;
                                    typedef _Arg2 second_argument_type;
                                    typedef _Result result_type;
                                    };
                                    //看看equal_to的定義:
                                    template <class _Tp>
                                    struct equal_to : public binary_function<_Tp,_Tp,bool>
                                    {
                                    bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; }
                                    };

                                    
如果你使用一個自定義的數據類型,如struct mystruct, 或者const char* 的字符串,如何使用比較函數?使用比較函數,有兩種方法. 第一種是:重載==操作符,利用equal_to;看看下面的例子:
struct mystruct{
                                    int iID;
                                    int  len;
                                    bool operator==(const mystruct & my) const{
                                    return (iID==my.iID) && (len==my.len) ;
                                    }
                                    };  

                                    
這樣,就可以使用equal_to< mystruct>作為比較函數了。另一種方法就是使用函數對象。自定義一個比較函數體:
struct compare_str{
                                    bool operator()(const char* p1, const char*p2) const{
                                    return strcmp(p1,p2)==0;
                                    }
                                    };  

                                    
有了compare_str,就可以使用hash_map了。
typedef hash_map<const char*, string, hash<const char*>, compare_str> StrIntMap;
                                    StrIntMap namemap;
                                    namemap["岳不群"]="華山派掌門人,人稱君子劍";
                                    namemap["張三豐"]="武當掌門人,太極拳創始人";
                                    namemap["東方不敗"]="第一高手,葵花寶典";

                                    

2.4 hash_map 函數

hash_map的函數和map的函數差不多。具體函數的參數和解釋,請參看:STL 編程手冊:Hash_map,這里主要介紹幾個常用函數。
  1. hash_map(size_type n) 如果講究效率,這個參數是必須要設置的。n 主要用來設置hash_map 容器中hash桶的個數。桶個數越多,hash函數發生沖突的概率就越小,重新申請內存的概率就越小。n越大,效率越高,但是內存消耗也越大。
  2. const_iterator find(const key_type& k) const. 用查找,輸入為鍵值,返回為迭代器。
  3. data_type& operator[](const key_type& k) . 這是我最常用的一個函數。因為其特別方便,可像使用數組一樣使用。不過需要注意的是,當你使用[key ]操作符時,如果容器中沒有key元素,這就相當于自動增加了一個key元素。因此當你只是想知道容器中是否有key元素時,你可以使用find。如果你希望插入該元素時,你可以直接使用[]操作符。
  4. insert 函數。在容器中不包含key值時,insert函數和[]操作符的功能差不多。但是當容器中元素越來越多,每個桶中的元素會增加,為了保證效率,hash_map會自動申請更大的內存,以生成更多的桶。因此在insert以后,以前的iterator有可能是不可用的。
  5. erase 函數。在insert的過程中,當每個桶的元素太多時,hash_map可能會自動擴充容器的內存。但在sgi stl中是erase并不自動回收內存。因此你調用erase后,其他元素的iterator還是可用的。

3 相關hash容器

hash 容器除了hash_map之外,還有hash_set, hash_multimap, has_multiset, 這些容器使用起來和set, multimap, multiset的區別與hash_map和map的區別一樣,我想不需要我一一細說了吧。

4 其他

這里列幾個常見問題,應該對你理解和使用hash_map比較有幫助。

4.1 hash_map和map的區別在哪里?

  • 構造函數。hash_map需要hash函數,等于函數;map只需要比較函數(小于函數).
  • 存儲結構。hash_map采用hash表存儲,map一般采用紅黑樹(RB Tree)實現。因此其memory數據結構是不一樣的。

4.2 什么時候需要用hash_map,什么時候需要用map?

總體來說,hash_map 查找速度會比map快,而且查找速度基本和數據數據量大小,屬于常數級別;而map的查找速度是log(n)級別。并不一定常數就比log(n)小,hash還有hash函數的耗時,明白了吧,如果你考慮效率,特別是在元素達到一定數量級時,考慮考慮hash_map。但若你對內存使用特別嚴格,希望程序盡可能少消耗內存,那么一定要小心,hash_map可能會讓你陷入尷尬,特別是當你的hash_map對象特別多時,你就更無法控制了,而且hash_map的構造速度較慢。

現在知道如何選擇了嗎?權衡三個因素: 查找速度, 數據量, 內存使用。

這里還有個關于hash_map和map的小故事,看看:http://dev.csdn.net/Develop/article/14/14019.shtm

4.3 如何在hash_map中加入自己定義的類型?

你只要做兩件事, 定義hash函數,定義等于比較函數。下面的代碼是一個例子:
-bash-2.05b$ cat my.cpp
                                    #include <hash_map>
                                    #include <string>
                                    #include <iostream>
                                    using namespace std;
                                    //define the class
                                    class ClassA{
                                    public:
                                    ClassA(int a):c_a(a){}
                                    int getvalue()const { return c_a;}
                                    void setvalue(int a){c_a;}
                                    private:
                                    int c_a;
                                    };
                                    //1 define the hash function
                                    struct hash_A{
                                    size_t operator()(const class ClassA & A)const{
                                    //  return  hash<int>(classA.getvalue());
                                    return A.getvalue();
                                    }
                                    };
                                    //2 define the equal function
                                    struct equal_A{
                                    bool operator()(const class ClassA & a1, const class ClassA & a2)const{
                                    return  a1.getvalue() == a2.getvalue();
                                    }
                                    };
                                    int main()
                                    {
                                    hash_map<ClassA, string, hash_A, equal_A> hmap;
                                    ClassA a1(12);
                                    hmap[a1]="I am 12";
                                    ClassA a2(198877);
                                    hmap[a2]="I am 198877";
                                    cout<<hmap[a1]<<endl;
                                    cout<<hmap[a2]<<endl;
                                    return 0;
                                    }
                                    -bash-2.05b$ make my
                                    c++  -O -pipe -march=pentiumpro  my.cpp  -o my
                                    -bash-2.05b$ ./my
                                    I am 12
                                    I am 198877

                                    
typedef map<Key, Value> KeyMap;

                                    

當你希望使用hash_map來替換的時候,只需要修改:

typedef hash_map<Key, Value> KeyMap;

                                    

其他的基本不變。當然,你需要注意是否有Key類型的hash函數和比較函數。

 

 

 

//////////////////////////////////////

參數使用說明

來源http://www.stlchina.org/twiki/bin/view.pl/Main/STLHashMap

/////////////////////////////////////////////

hash_map<Key, Data, HashFcn, EqualKey, Alloc>

Category: containers

Description

Hash_map 是一種使用hash 關聯容器,把Key 和value數據對應存儲; Hash_map 同樣是一個Pair 的關聯容器,這意味著其元素類型是pair<const Key, Data>; Hash_map 還是Unique 關聯容器,即使用EqualKey比較函數來判斷不存在兩個元素的key值相等。

由于hash_map在通過key值查找時具有很高的效率,所以hash_map對于一些互不相干的元素的存儲非常有用。如果元素的某種順序比較重要,使用map更合適一些。

Example

struct eqstr
                                    {
                                    bool operator()(const char* s1, const char* s2) const
                                    {
                                    return strcmp(s1, s2) == 0;
                                    }
                                    };
                                    int main()
                                    {
                                    hash_map<const char*, int, hash<const char*>, eqstr> months;
                                    months["january"] = 31;
                                    months["february"] = 28;
                                    months["march"] = 31;
                                    months["april"] = 30;
                                    months["may"] = 31;
                                    months["june"] = 30;
                                    months["july"] = 31;
                                    months["august"] = 31;
                                    months["september"] = 30;
                                    months["october"] = 31;
                                    months["november"] = 30;
                                    months["december"] = 31;
                                    cout << "september -> " << months["september"] << endl;
                                    cout << "april     -> " << months["april"] << endl;
                                    cout << "june      -> " << months["june"] << endl;
                                    cout << "november  -> " << months["november"] << endl;
                                    }

                                    

Definition Defined in the header hash_map, and in the backward-compatibility header hash_map.h. This class is an SGI extension; it is not part of the C++ standard.

Template parameters

 

 

 

 

 

 

Parameter Description

 

Default
Key The hash_map's key type. This is also defined as hash_map::key_type.  

 

Data The hash_map's data type. This is also defined as hash_map::data_type.  
HashFcn The hash function used by the hash_map. This is also defined as hash_map::hasher. hash<Key>
EqualKey The hash_map key equality function: a binary predicate that determines whether two keys are equal. This is also defined as hash_map::key_equal. equal_to<Key>

 

Alloc The hash_map's allocator, used for all internal memory management. alloc

Members

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Member Where defined Description
key_type Associative Container The hash_map's key type, Key.

 

data_type Pair Associative Container The type of object associated with the keys.
value_type Pair Associative Container The type of object, pair<const key_type, data_type>, stored in the hash_map.
hasher Hashed Associative Container The hash_map's hash function.
key_equal Hashed Associative Container Function object that compares keys for equality.
pointer Container Pointer to T.
reference Container Reference to T

const_reference

Container Const reference to T
size_type

 

Container An unsigned integral type.
difference_type Container

 

A signed integral type.
iterator Container Iterator used to iterate through a hash_map. [1]

 

const_iterator Container Const iterator used to iterate through a hash_map.
iterator begin() Container Returns an iterator pointing to the beginning of the hash_map.

 

iterator end() Container Returns an iterator pointing to the end of the hash_map.

 

const_iterator begin() const Container Returns an const_iterator pointing to the beginning of the hash_map.

 

const_iterator end() const Container Returns an const_iterator pointing to the end of the hash_map.

 

size_type size() const Container Returns the size of the hash_map.
size_type max_size() const Container Returns the largest possible size of the hash_map.
bool empty() const Container true if the hash_map's size is 0.

 

size_type bucket_count() const Hashed Associative Container Returns the number of buckets used by the hash_map.
void resize(size_type n) Hashed Associative Container Increases the bucket count to at least n.
hasher hash_funct() const Hashed Associative Container Returns the hasher object used by the hash_map.

 

key_equal key_eq() const Hashed Associative Container Returns the key_equal object used by the hash_map.

 

hash_map() Container Creates an empty hash_map.
hash_map(size_type n) Hashed Associative Container Creates an empty hash_map with at least n buckets.

 

hash_map(size_type n,
                                                const hasher& h)
                                                
Hashed Associative Container Creates an empty hash_map with at least n buckets, using h

as the hash function.

hash_map(size_type n,
                                                const hasher& h,
                                                const key_equal& k)
                                                
Hashed Associative Container

 

Creates an empty hash_map with at least n buckets, using h as the hash function and k as the key equal function.
template <class InputIterator>
                                                hash_map(InputIterator f, InputIterator l)
                                                [2]
                                                
Unique Hashed Associative Container

 

Creates a hash_map with a copy of a range.
template <class InputIterator>
                                                hash_map(InputIterator f, InputIterator l,
                                                size_type n)
                                                [2]
                                                
Unique Hashed Associative Container Creates a hash_map with a copy of a range and a bucket count of at least n.
template <class InputIterator>
                                                hash_map(InputIterator f, InputIterator l,
                                                size_type n, const hasher& h)
                                                [2]
                                                
Unique Hashed Associative Container Creates a hash_map with a copy of a range and a bucket count of at least n, using h as the hash function.

 

template <class InputIterator>
                                                hash_map(InputIterator f, InputIterator l,
                                                size_type n, const hasher& h,
                                                const key_equal& k)
                                                [2]
                                                

 

Unique Hashed Associative Container Creates a hash_map with a copy of a range and a bucket count of at least n, using h as the hash function and k as the key equal function.
hash_map(const hash_map&) Container The copy constructor.
hash_map& operator=(const hash_map&) Container The assignment operator
void swap(hash_map&) Container Swaps the contents of two hash_maps.
pair<iterator, bool>
                                                insert(const value_type& x)
                                                
Unique Associative Container Inserts x into the hash_map.

 

template <class InputIterator>
                                                void insert(InputIterator f, InputIterator l)
                                                [2]
                                                
Unique Associative Container

 

Inserts a range into the hash_map.
void erase(iterator pos) Associative Container Erases the element pointed to by pos.
size_type erase(const key_type& k) Associative Container

 

Erases the element whose key is k.
void erase(iterator first, iterator last) Associative Container Erases all elements in a range.
void clear() Associative Container Erases all of the elements.
const_iterator find(const key_type& k) const Associative Container Finds an element whose key is k.

 

iterator find(const key_type& k) Associative Container Finds an element whose key is k.

 

size_type count(const key_type& k) const Unique Associative Container Counts the number of elements whose key is k.

 

pair<const_iterator, const_iterator>
                                                equal_range(const key_type& k) const
                                                
Associative Container

 

Finds a range containing all elements whose key is k.
pair<iterator, iterator>
                                                equal_range(const key_type& k)
                                                

 

Associative Container Finds a range containing all elements whose key is k.
data_type&
                                                operator[](const key_type& k) [3]
                                                
hash_map See below.

 

bool operator==(const hash_map&,
                                                const hash_map&)
                                                
Hashed Associative Container Tests two hash_maps for equality. This is a global function, not a member function.

New members

These members are not defined in the Unique Hashed Associative Container and Pair Associative Container requirements, but are specific to hash_map.

 

 

 

Member Description
data_type&
                                                operator[](const key_type& k) [3]
                                                
Returns a reference to the object that is associated with a particular key. If the hash_map does not already contain such an object, operator[] inserts the default object data_type(). [3]

 

Notes

[1] Hash_map::iterator is not a mutable iterator, because hash_map::value_type is not Assignable. That is, if i is of type hash_map::iterator and p is of type

hash_map::value_type, then *i = p is not a valid expression. However, hash_map::iterator isn't a constant iterator either, because it can be used to modify the object that it points to. Using the same notation as above, (*i).second = p is a valid expression.

[2] This member function relies on member template functions, which at present (early 1998) are not supported by all compilers. If your compiler supports member templates, you can call this function with any type of input iterator. If your compiler does not yet support member templates, though, then the arguments must either be of type const value_type* or of type

hash_map::const_iterator.

[3] Since operator[] might insert a new element into the hash_map, it can't possibly be a const member function. Note that the definition of operator[] is extremely simple: m[k] is equivalent to

(*((m.insert(value_type(k, data_type()))).first)).second. Strictly speaking, this member function is unnecessary: it exists only for convenience.

posted on 2008-09-08 23:23 雪竹的天空( theorix ) 閱讀(7008) 評論(0)  編輯 收藏 引用 所屬分類: 算法資料
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一区二区成人精品| 欧美日韩视频在线观看一区二区三区| 亚洲日本中文字幕区| 激情成人中文字幕| 国内外成人免费激情在线视频网站| 国产精品一区二区三区观看| 欧美吻胸吃奶大尺度电影| 欧美三级日本三级少妇99| 国产精品久久久久久av下载红粉| 欧美人成在线| 国产精品v欧美精品v日本精品动漫| 国产精品国产精品| 激情亚洲网站| 亚洲四色影视在线观看| 欧美一区二区三区在线观看视频| 性视频1819p久久| 免费成人黄色片| 亚洲福利在线看| 亚洲精品一区二区三区婷婷月| 99热免费精品| 欧美在线一二三区| 免费试看一区| 99视频在线观看一区三区| 午夜天堂精品久久久久 | 亚洲专区一区二区三区| 亚洲欧美国产毛片在线| 老牛影视一区二区三区| 国产精品大片wwwwww| 一区二区在线免费观看| 国产精品99久久久久久www| 久久久久久久久一区二区| 亚洲人成高清| 亚洲小视频在线观看| 另类春色校园亚洲| 国产精品免费在线| 亚洲国产精品va在线看黑人动漫 | 国产酒店精品激情| 91久久久久| 久久精品免视看| 一区二区久久| 欧美激情一区在线观看| 在线成人av网站| 午夜视频久久久久久| 亚洲人成亚洲人成在线观看图片| 欧美在线视频免费| 国产精品天美传媒入口| 一区二区三区不卡视频在线观看 | 国产精品美女在线| 日韩午夜免费视频| 欧美77777| 久久久久久9| 黄色亚洲精品| 久久视频国产精品免费视频在线| 亚洲校园激情| 国产精品美腿一区在线看 | 香蕉尹人综合在线观看| 国产精品www994| 亚洲午夜精品视频| 日韩午夜在线视频| 欧美日韩一区二区免费在线观看 | 欧美激情自拍| 美女精品自拍一二三四| 激情欧美一区二区三区在线观看| 久久精品欧美日韩| 久久激情综合网| 在线成人av| 亚洲大片免费看| 欧美成人在线网站| 一本大道av伊人久久综合| 亚洲欧洲精品成人久久奇米网| 欧美va天堂| 欧美激情小视频| 亚洲日韩欧美视频一区| 亚洲高清在线视频| 欧美激情网站在线观看| 亚洲婷婷免费| 欧美一区二区三区免费视频| 激情综合网址| 欧美激情久久久久久| 欧美日本簧片| 香蕉成人伊视频在线观看 | 欧美有码视频| 精品成人在线视频| 最近中文字幕日韩精品| 欧美视频在线观看| 久久高清国产| 免费成人av在线| 亚洲一区二区三区欧美| 欧美亚洲一级| 亚洲麻豆国产自偷在线| 一区二区三区 在线观看视| 国产女主播一区二区| 乱人伦精品视频在线观看| 欧美成人免费全部观看天天性色| 亚洲视频播放| 久久久久免费视频| 亚洲一区免费视频| 久久天天狠狠| 亚洲欧美日韩精品久久久久| 欧美中文字幕在线观看| 日韩视频在线观看一区二区| 亚洲欧美国产视频| 日韩小视频在线观看专区| 亚洲欧美日本国产有色| 亚洲日本免费| 欧美影片第一页| 99国产精品视频免费观看一公开 | 欧美国产在线电影| 欧美一区二区视频在线观看2020| 狂野欧美激情性xxxx| 欧美亚洲一区| 欧美日韩亚洲成人| 欧美成年视频| 国产一区999| av成人黄色| 亚洲伦伦在线| 欧美成人tv| 久久综合伊人77777麻豆| 国产精品初高中精品久久| 亚洲国产精品久久91精品| 国产亚洲电影| 亚洲一区日本| 亚洲视频在线二区| 欧美成人激情在线| 免费在线日韩av| 精品电影在线观看| 欧美在线中文字幕| 欧美在线播放一区二区| 欧美日韩福利| 亚洲精品一区二区三区在线观看| 亚洲第一久久影院| 久久精品免视看| 久久精品国产综合| 国产一区二区精品久久| 欧美一区二区三区电影在线观看| 欧美视频中文在线看| 亚洲精品婷婷| 一区二区三区高清在线观看| 欧美日韩国产成人高清视频| 亚洲国产三级在线| 亚洲毛片视频| 欧美色欧美亚洲另类二区| 日韩一二三在线视频播| 一区二区三区精品在线| 国产精品av免费在线观看| 99在线热播精品免费| 亚洲一区二区在线免费观看视频| 欧美色精品天天在线观看视频| 亚洲美女一区| 亚洲一区中文字幕在线观看| 国产精品嫩草影院一区二区| 亚洲一区二区视频| 欧美影院在线播放| 激情婷婷亚洲| 欧美男人的天堂| 中日韩视频在线观看| 欧美专区18| 亚洲第一二三四五区| 欧美精品免费在线观看| 亚洲视频在线观看免费| 久久久久国产一区二区| 亚洲国产老妈| 欧美午夜不卡| 久久精品久久综合| 91久久夜色精品国产九色| 亚洲欧美激情四射在线日| 国外成人性视频| 欧美理论视频| 欧美一区国产一区| 亚洲三级影院| 久久久精品五月天| 99热免费精品| 国产中文一区二区三区| 欧美—级高清免费播放| 午夜免费日韩视频| 亚洲激情中文1区| 欧美一区二区三区四区视频| 亚洲日本欧美天堂| 国产视频在线观看一区二区三区 | 国产精品久99| 久久性天堂网| 一区二区免费看| 欧美成人免费观看| 性欧美videos另类喷潮| 日韩午夜在线观看视频| 国产最新精品精品你懂的| 欧美日韩国产成人精品| 久久一区亚洲| 欧美一级片久久久久久久| 亚洲精品少妇网址| 麻豆国产va免费精品高清在线| 亚洲伊人久久综合| 最近中文字幕mv在线一区二区三区四区| 欧美性猛片xxxx免费看久爱| 欧美chengren| 麻豆91精品| 久久综合色一综合色88| 欧美影院视频| 亚洲免费中文| 亚洲午夜久久久久久久久电影院|