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

雪竹的天空

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 ) 閱讀(7012) 評論(0)  編輯 收藏 引用 所屬分類: 算法資料

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美亚洲一区在线| 亚洲午夜视频在线观看| 国产偷国产偷精品高清尤物| 在线不卡a资源高清| 亚洲专区在线视频| 一本色道久久| 久久综合给合久久狠狠色| 欧美午夜三级| 亚洲精品乱码视频| 一区二区三区国产在线| 美女在线一区二区| 亚洲香蕉网站| 欧美日韩高清在线播放| 国产精品久久二区| 亚洲美女免费精品视频在线观看| 亚洲综合色视频| 久久综合一区二区| 亚洲女同同性videoxma| 欧美日韩免费视频| 伊人春色精品| 久久久久久久久久久久久9999| 在线亚洲欧美| 欧美电影免费观看高清| 国产性猛交xxxx免费看久久| 日韩视频在线播放| 欧美1区2区3区| 久久手机精品视频| 在线观看av不卡| 久久精品国产91精品亚洲| 91久久线看在观草草青青| 久久综合综合久久综合| 欧美视频精品在线| 在线视频亚洲一区| 99精品视频免费| 欧美日韩在线观看视频| 一区二区三区日韩在线观看| 亚洲欧洲精品一区二区| 欧美日韩精品免费观看视频| 在线亚洲高清视频| 亚洲香蕉网站| 国内免费精品永久在线视频| 久热精品在线| 免费不卡中文字幕视频| 亚洲国产精品激情在线观看 | 亚洲自拍偷拍色片视频| 亚洲午夜精品一区二区| 国产精品爽爽爽| 久久美女性网| 蜜臀久久久99精品久久久久久| 亚洲日韩欧美视频| 亚洲精品久久久久久久久久久 | 国产乱码精品一区二区三区忘忧草| 午夜欧美大片免费观看| 欧美一区午夜精品| 亚洲激情国产| 一区二区高清视频在线观看| 国产日韩欧美制服另类| 欧美福利在线| 欧美午夜视频网站| 久久精品中文字幕一区二区三区| 久久免费国产精品1| 在线亚洲一区观看| 久久久久国产一区二区| 亚洲精品在线观看免费| 国产精品一区二区三区四区| 免费黄网站欧美| 欧美性天天影院| 老司机免费视频一区二区三区| 欧美大片在线影院| 久久本道综合色狠狠五月| 男女精品网站| 久久成人18免费观看| 女主播福利一区| 亚洲字幕一区二区| 美腿丝袜亚洲色图| 欧美在线播放一区| 欧美日韩18| 欧美不卡视频一区发布| 国产精品一区在线观看| 久久综合九色综合欧美狠狠| 久久综合九色综合网站| 小辣椒精品导航| 欧美国产日本高清在线| 久久久久久黄| 国产精品福利影院| 亚洲黄色成人网| 黄色一区二区三区| 亚洲一区二区三区精品动漫| 国产婷婷色一区二区三区在线| 亚洲区一区二| 欧美一级成年大片在线观看| 在线日本高清免费不卡| 一本色道久久综合| 亚洲成人在线网| 午夜视频久久久久久| 久久亚洲精选| 国产精品色午夜在线观看| 亚洲国产一区二区三区青草影视| 亚洲少妇诱惑| 宅男噜噜噜66一区二区66| 麻豆av一区二区三区| 久久久久国产精品厨房| 国产精品综合网站| 亚洲欧美国产视频| 亚洲欧美成人综合| 欧美日韩另类视频| 亚洲精选中文字幕| 99国产精品久久久久老师| 可以看av的网站久久看| 免费亚洲一区| 亚洲大胆美女视频| 榴莲视频成人在线观看| 欧美.www| 亚洲免费观看视频| 欧美日本不卡| 99精品国产高清一区二区| 韩日欧美一区二区| 欧美在线亚洲综合一区| 久久免费视频在线观看| 国产日韩欧美电影在线观看| 亚洲欧美在线x视频| 欧美在线综合视频| 精品成人国产| 亚洲国产美女久久久久| 欧美一区二区三区啪啪| 久久久久国产精品一区二区| 一区在线视频| 欧美一区二区三区在| 亚洲美女区一区| 午夜欧美大片免费观看| 久久精品国产一区二区电影| 欧美喷潮久久久xxxxx| 欧美成人69av| 一区在线播放| 欧美成人在线网站| 欧美韩日精品| 日韩亚洲国产欧美| 国产精品久久久久久妇女6080 | 欧美亚洲在线视频| 欧美日韩精品三区| 亚洲国产欧美精品| 亚洲一级免费视频| 国产视频在线一区二区| 麻豆精品国产91久久久久久| 亚洲美女黄网| 久久综合九色99| 亚洲午夜久久久久久久久电影院 | 欧美精品v日韩精品v国产精品| 最新高清无码专区| 久久精品二区亚洲w码| 亚洲人成在线免费观看| 国产精品久久久91| 亚洲中字黄色| 亚洲午夜影视影院在线观看| 在线播放日韩欧美| 欧美调教视频| 米奇777在线欧美播放| 亚洲午夜av在线| 欧美福利视频在线| 欧美中文字幕在线观看| 亚洲免费精彩视频| 极品尤物av久久免费看 | 欧美日韩在线精品| 免费在线亚洲| 宅男噜噜噜66一区二区| 欧美大片一区| 久久se精品一区二区| 亚洲青色在线| 国产亚洲日本欧美韩国| 欧美日韩国产在线| 玖玖综合伊人| 久久精品视频在线观看| 亚洲一二三区视频在线观看| 欧美激情第10页| 久久人人97超碰精品888| 欧美影片第一页| 亚洲欧美久久久久一区二区三区| 欧美成人有码| 噜噜噜在线观看免费视频日韩| 欧美中文在线字幕| 亚洲专区免费| 亚洲砖区区免费| 中文在线资源观看网站视频免费不卡 | 亚洲欧洲在线看| 99国产精品久久久久久久| 久久精品99久久香蕉国产色戒| 亚洲大片免费看| 国内精品一区二区| 国产亚洲精品一区二区| 国产九九视频一区二区三区| 国产精品扒开腿做爽爽爽软件| 欧美日本不卡| 欧美日韩国产欧| 欧美喷潮久久久xxxxx| 欧美成人69| 欧美国产精品人人做人人爱| 欧美va亚洲va日韩∨a综合色| 久久免费精品视频| 你懂的亚洲视频| 国产精品卡一卡二|