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

雪竹的天空

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| 欧美激情五月| 在线日韩av片| 猫咪成人在线观看| 欧美另类视频| 艳妇臀荡乳欲伦亚洲一区| 亚洲天堂网在线观看| 国产精品xvideos88| 狂野欧美激情性xxxx欧美| 欧美日韩ab| 亚洲最新合集| 久久精品动漫| 在线观看中文字幕不卡| 亚洲精品国精品久久99热| 欧美精品观看| 久久久精品国产免费观看同学| 欧美人体xx| 尤物视频一区二区| 久久一区二区三区四区| 欧美精品久久久久久久久老牛影院| 亚洲欧美国产制服动漫| 亚洲视频免费在线观看| 国产精品国产三级国产aⅴ入口| 亚洲综合日韩在线| 蜜桃av一区二区三区| 亚洲毛片在线看| 亚洲人成在线观看网站高清| 国产日韩欧美夫妻视频在线观看| 久久九九精品99国产精品| 欧美日本免费一区二区三区| 蜜桃伊人久久| 欧美日韩播放| 另类av一区二区| 国产亚洲成av人片在线观看桃| 亚洲精品女av网站| 欧美日本成人| 亚洲国产美女| 国产麻豆综合| 蜜臀久久99精品久久久画质超高清| 国产精品扒开腿爽爽爽视频| 亚洲国产日本| 亚洲精品美女久久7777777| av成人福利| 国内精品久久久久影院色| 麻豆国产va免费精品高清在线| 国产精品自拍视频| 亚洲图片欧美一区| 亚洲欧美综合国产精品一区| 久久视频这里只有精品| 亚洲小说欧美另类婷婷| 久久狠狠亚洲综合| 久久久久久综合| 欧美日韩在线免费| 亚洲在线网站| 国产精品夜夜夜| 亚洲人成网站色ww在线| 99精品热视频只有精品10| 欧美在线视频全部完| 这里是久久伊人| 欧美性猛交xxxx乱大交蜜桃| 一区二区成人精品| 亚洲国产精品一区二区尤物区| 久热爱精品视频线路一| 欧美一区二区啪啪| 欧美日韩国产一区二区三区| 亚洲美女网站| 亚洲日本欧美天堂| 欧美日韩国产成人在线观看| 亚洲视频成人| 久久婷婷影院| 亚洲美女av电影| 国产精品久久久久久久久动漫| 欧美一二区视频| 亚洲国产精品成人综合色在线婷婷| 99精品视频一区二区三区| 国产精品久久久久久一区二区三区 | 欧美福利小视频| 国产欧美在线观看| 久久狠狠婷婷| 99国产精品久久久久久久| 欧美亚洲色图校园春色| 国产精品va在线播放| 久久一区二区三区超碰国产精品| 欧美激情精品久久久久久大尺度 | 免费永久网站黄欧美| 日韩视频免费| 国产一区免费视频| 欧美人与性动交α欧美精品济南到| 亚洲影视中文字幕| 一本久久知道综合久久| 国产精品久久久久毛片软件| 久久人人爽人人爽爽久久| 99精品免费视频| 欧美成人精品| 夜夜嗨网站十八久久| 国产欧美一区二区色老头| 欧美xxx成人| 亚洲美女在线看| 麻豆av一区二区三区久久| 亚洲性视频网站| 亚洲精品一区二区三| 国内一区二区三区在线视频| 久久婷婷国产综合尤物精品 | 麻豆精品一区二区av白丝在线| 亚洲天堂免费观看| 国产精品日韩电影| 欧美精品一区三区在线观看| 久久国产精品久久国产精品| 亚洲图片激情小说| 99香蕉国产精品偷在线观看| 欧美大色视频| 毛片一区二区| 久久一二三四| 美女精品在线观看| 久久成人这里只有精品| 一区精品久久| 欧美精品在线免费| 老色鬼精品视频在线观看播放| 午夜精品电影| 亚洲激情小视频| 欧美一级在线亚洲天堂| 亚洲视频二区| 在线午夜精品| 国产精品99久久久久久有的能看 | 亚洲精品国产精品久久清纯直播| 国内一区二区在线视频观看| 韩日视频一区| 韩国一区二区三区在线观看| 国产视频不卡| 国内精品亚洲| 精品不卡视频| 亚洲欧洲精品一区二区三区波多野1战4| 欧美日韩国产在线播放| 欧美日韩精品在线视频| 欧美性猛交xxxx乱大交蜜桃| 国产精品久久一级| 国产深夜精品| 亚洲高清影视| 99视频一区| 午夜精品久久久久久久久久久| 欧美一区二区播放| 久久久亚洲精品一区二区三区| 欧美成人r级一区二区三区| 亚洲国产你懂的| 在线视频亚洲一区| 性亚洲最疯狂xxxx高清| 一区二区欧美视频| 亚洲欧美日韩国产中文在线| 欧美一区二区三区免费视频| 麻豆成人在线| 国产精品欧美日韩一区| 国产自产在线视频一区| 欧美性开放视频| 久久精品视频在线播放| 免费精品99久久国产综合精品| 亚洲淫性视频| 久久全球大尺度高清视频| 欧美国产精品专区| 国产精品网站一区| **网站欧美大片在线观看| 妖精视频成人观看www| 欧美一区二区三区日韩| 欧美国产成人在线| 亚洲校园激情| 欧美国产日韩一区二区三区| 国产精品日韩二区| 亚洲日本中文字幕| 欧美一区二区三区四区夜夜大片| 免费成人黄色| 亚洲综合国产| 性久久久久久| 欧美美女福利视频| 韩国精品主播一区二区在线观看| 99视频一区二区三区| 久久亚洲一区| 亚洲一区二区毛片| 欧美金8天国| 在线观看日韩www视频免费| 亚洲欧美日韩国产一区二区| 欧美成人日本| 欧美一区网站| 国产精品久久网| 亚洲午夜激情免费视频| 麻豆国产精品va在线观看不卡| 亚洲一区二区影院| 国产精品99免费看|