午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁 > 知識庫 > Go語言之自定義集合Set

Go語言之自定義集合Set

熱門標簽:百度地圖標注搜索關鍵詞 電銷機器人可以補救房產中介嗎 谷歌便利店地圖標注 騰訊外呼系統價格 ?兓? 成都呼叫中心外呼系統平臺 浙江人工智能外呼管理系統 電梯外呼訪客系統 最短的地圖標注

一、Go語言實戰——自定義集合Set

在Go語言中有作為Hash Table實現的字典(Map)類型,但標準數據類型中并沒有集合(Set)這種數據類型。比較 Set Map 的主要特性,有類似特性如下:

    它們中的元素都是不可重復的。

    它們都只能用迭代的方式取出其中的所有元素。

    對它們中的元素進行迭代的順序都是與元素插入順序無關的,同時也不保證任何有序性。

但是,它們之間也有一些區別,如下:

Set 的元素是一個單一的值,而 Map 的元素則是一個鍵值對。

Set 的元素不可重復指的是不能存在任意兩個單一值相等的情況。Map的元素不可重復指的是任意兩個鍵值對中的鍵的值不能相等。

從上面的特性可知,可以把集合類型(Set)作為字典類型(Map)的一個簡化版本。也就是說,可以用 Map 來編寫一個 Set 類型的實現。實際上,在Java語言中,java.util.HashSet 類就是用 java.util.HashMap 類作為底層支持的。所以這里就從HashSet出發,逐步抽象出集合Set

1. 定義HashSet

首先,在工作區的 src 目錄的代碼包 basic/set(可以自行定義,但后面要保持一致)中,創建一個名為 hash_set.go 的源碼文件。

根據代碼包 basic/set 可知,源碼文件 hash_set.go 的包聲明語句(關于這個一些規則可以看前面的系列博文)如下:

package set

上面提到可以將集合類型作為字典類型的一個簡化版本。現在我們的 HashSet 就以字典類型作為其底層的實現。HashSet 聲明如下:

type HashSet struct {
  m map[interface{}]bool
}

如上聲明 HashSet 類型中的唯一的字段的類型是 map[interface{}]bool。選擇這樣一個字典類型是因為通過將字典 m 的鍵類型設置為 interface{},HashSet 的元素可以是任何類型的,因為這里需要使用 m 的值中的鍵來存儲 HashSet 類型的元素值。那使用 bool 類型作為 m 的值的元素類型的好處如下:

從值的存儲形式的角度看,bool 類型值只占用一個字節。

從值的表示形式的角度看,bool 類型的值只有兩個—true 和 false。并且,這兩個值度都是預定義常量。

bool 類型作為值類型更有利于判斷字典類型值中是否存在某個鍵。例如:如果在向 m 的值添加鍵值對的時候總是以 true 作為其中的元素的值,則索引表達式 m[“a”] 的結果值總能體現出在m的值中是否包含鍵為“a”的鍵值對。對于 map[interface{}]bool 類型的值來說,如下:

if m["a"] {// 判斷是否m中包含鍵為“a”的鍵值對
  //省略其他語句
}

如上 HashSet 類型的基本結構已確定了,現在考慮如何初始化 HashSet 類型值。由于字典類型的零值為 nil,而用 new 函數來創建一個 HashSet 類型值,也就是 new(HashSet).m 的求值結果將會是一個 nil (關于 new 函數可以查閱本人另一篇博文Go語言學習筆記5)。因此,這里需要編寫一個專門用于創建和初始化 HashSet 類型值的函數,該函數聲明如下:

func NewHashSet() *HashSet {
  return HashSet{m: make(map[interface{}]bool)}
}

如上可以看到,使用make函數對字段m進行了初始化。同時注意觀察函數 NewHashSet 的結果聲明的類型是 *HashSet 而不是 HashSet,目的是讓這個結果值的方法集合中包含調用接收者類型為 HashSet *HashSet 的所有方法。這樣做的好處將在后面編寫 Set 接口類型的時候再予以說明。

2.實現HashSet的基本功能

依據其他編程語言中的 HashSet 類型可知,它們大部分應該提供的基本功能如下:

添加元素值。

刪除元素值。

清除所有元素值。

判斷是否包含某個元素值。

獲取元素值的數量。

判斷與其他HashSet類型值是否相同。

獲取所有元素值,即生成可迭代的快照。

獲取自身的字符串表示形式。

現在對這些功能一一實現,讀者可自行實現,以下僅供參考。

(1).添加元素值

//方法Add會返回一個bool類型的結果值,以表示添加元素值的操作是否成功。
//方法Add的聲明中的接收者類型是*HashSet。
func (set *HashSet) Add(e interface{}) bool {
  if !set.m[e] {//當前的m的值中還未包含以e的值為鍵的鍵值對
    set.m[e] = true//將鍵為e(代表的值)、元素為true的鍵值對添加到m的值當中
    return true //添加成功
  }
  return false //添加失敗
}

這里使用 *HashSet 而不是 HashSet,主要是從節約內存空間的角度出發,分析如下:

Add 方法的接收者類型為 HashSet 的時候,對它的每一次調用都需要對當前 HashSet 類型值進行一次復制。雖然在 HashSet 類型中只有一個引用類型的字段,但是這也是一種開銷。而且這里還沒有考慮 HashSet 類型中的字段可能會變得更多的情況。

Add 方法的接收者類型為 *HashSet 的時候,對它進行調用時復制的當前 *HashSet 的類型值只是一個指針值。在大多數情況下,一個指針值占用的內存空間總會被它指向的那個其他類型的值所占用的內存空間小。無論一個指針值指向的那個其他類型值所需的內存空間有多么大,它所占用的內存空間總是不變的。

(2).刪除元素值

//調用delete內建函數刪除HashSet內部支持的字典值
func (set *HashSet) Remove(e interface{}) {
  delete(set.m, e)//第一個參數為目標字典類型,第二個參數為要刪除的那個鍵值對的鍵
}

(3).清除所有元素

//為HashSet中的字段m重新賦值
func (set *HashSet) Clear() {
  set.m = make(map[interface{}]bool)
}

如果接收者類型是 HashSet,該方法中的賦值語句的作用只是為當前值的某個復制品中的字段m賦值而已,而當前值中的字段 m 則不會被重新賦值。方法 Clear 中的這條賦值語句被執行之后,當前的 HashSet 類型值中的元素就相當于被清空了。已經與字段 m 解除綁定的那個舊的字典值由于不再與任何程序實體存在綁定關系而成為了無用的數據。它會在之后的某一時刻被Go語言的垃圾回收器發現并回收。

(4).判斷是否包含某個元素值。

//方法Contains用于判斷其值是否包含某個元素值。
//這里判斷結果得益于元素類型為bool的字段m
func (set *HashSet) Contains(e interface{}) bool {
  return set.m[e]
}

當把一個 interface{} 類型值作為鍵添加到一個字典值的時候,Go語言會先獲取這個 interface{} 類型值的實際類型(即動態類型),然后再使用與之對應的 hash 函數對該值進行 hash 運算,也就是說,interface{} 類型值總是能夠被正確地計算出 hash 值。但是字典類型的鍵不能是函數類型、字典類型或切片類型,否則會引發一個運行時恐慌,并提示如下:
panic: runtime error: hash of unhashable type 某個函數類型、字典類型或切片類型的名稱>

(5).獲取元素值的數量。

//方法Len用于獲取HashSet元素值數量
func (set *HashSet) Len() int {
  return len(set.m)
}

(6).判斷與其他HashSet類型值是否相同。

//方法Same用來判斷兩個HashSet類型值是否相同
func (set *HashSet) Same(other *HashSet) bool {
  if other == nil {
    return false
  }
  if set.Len() != other.Len() {
    return false
  }
  for key := range set.m {
    if !other.Contains(key) {
      return false
    }
  }
  return true
}

兩個 HashSet 類型值相同的必要條件是,它們包含的元素應該是完全相同的。由于 HashSet 類型值中的元素的迭代順序總是不確定的,所以也就不用在意兩個值在這方面是否一致。如果要判斷兩個 HashSet 類型值是否是同一個值,就需要利用指針運算進行內存地址的比較。

(7).獲取所有元素值,即生成可迭代的快照。

所謂 快照,就是目標值在某一個時刻的映像。對于一個 HashSet 類型值來說,它的快照中的元素迭代順序總是可以確定的,快照只反映了該 HashSet 類型值在某一個時刻的狀態。另外,還需要從元素可迭代且順序可確定的數據類型中選取一個作為快照的類型。這個類型必須是以單值作為元素的,所以字典類型最先別排除。又由于 HashSet 類型值中的元素數量總是不固定的,所以無法用一個數組類型的值來表示它的快照。如上分析可知,Go語言中可以使用的快照的類型應該是一個切片類型或者通道類型。

//方法Elements用于生成快照
func (set *HashSet) Elements() []interface{} {
  initialLen := len(set.m)//獲取HashSet中字段m的長度,即m中包含元素的數量
  //初始化一個[]interface{}類型的變量snapshot來存儲m的值中的元素值
  snapshot := make([]interface{}, initialLen)
  actualLen := 0
  //按照既定順序將迭代值設置到快照值(變量snapshot的值)的指定元素位置上,這一過程并不會創建任何新值。
  for key := range set.m {
    if actualLen  initialLen {
      snapshot[actualLen] = key
    } else {//m的值中的元素數量有所增加,使得實際迭代的次數大于先前初始化的快照值的長度
      snapshot = append(snapshot, key)//使用append函數向快照值追加元素值。
    }
    actualLen++//實際迭代的次數
  }
  //對于已被初始化的[]interface{}類型的切片值來說,未被顯示初始化的元素位置上的值均為nil。
  //m的值中的元素數量有所減少,使得實際迭代的次數小于先前初始化的快照值的長度。
  //這樣快照值的尾部存在若干個沒有任何意義的值為nil的元素,
  //可以通過snapshot = snapshot[:actualLen]將無用的元素值從快照值中去掉。
  if actualLen  initialLen {
    snapshot = snapshot[:actualLen]
  }
  return snapshot
}

注意:Elements 方法中針對并發訪問和修改 m 的值的情況采取了一些措施。但是由于m的值本身并不是并發安全的,所以并不能保證 Elements 方法的執行總會準確無誤。要做到真正的并發安全,還需要一些輔助的手段,比如讀寫互斥量。

(8).獲取自身的字符串表示形式。

//這個String方法的簽名算是一個慣用法。 //代碼包fmt中的打印函數總會使用參數值附帶的具有如此簽名的String方法的結果值作為該參數值的字符串表示形式。
func (set *HashSet) String() string {
  var buf bytes.Buffer//作為結果值的緩沖區
  buf.WriteString("HashSet{")
  first := true
  for key := range set.m {
    if first {
      first = false
    } else {
      buf.WriteString(",")
    }
    buf.WriteString(fmt.Sprintf("%v", key))
  }
  //n := 1
  //for key := range set.m {
  // buf.WriteString(fmt.Sprintf("%v", key))
  // if n == len(set.m) {//最后一個元素的后面不添加逗號
  // break;
  // } else {
  // buf.WriteString(",")
  // }
  // n++;
  //}
  buf.WriteString("}")
  return buf.String() 
}

如上已經完整地編寫了一個具備常用功能的Set的實現類型,后面將講解更多的高級功能來完善它。

3.高級功能

集合 Set 的真包含的判斷功能。根據集合代數中的描述,如果集合 A 真包含了集合 B,那么就可以說集合 A 是集合 B 的一個超集。

// 判斷集合 set 是否是集合 other 的超集 
func (set *HashSet) IsSuperset(other *HashSet) bool {
  if other == nil {//如果other為nil,則other不是set的子集
    return false
  }
  setLen := set.Len()//獲取set的元素值數量
  otherLen := other.Len()//獲取other的元素值數量
  if setLen == 0 || setLen == otherLen {//set的元素值數量等于0或者等于other的元素數量
    return false
  }
  if setLen > 0  otherLen == 0 {//other為元素數量為0,set元素數量大于0,則set也是other的超集
    return true
  }
  for _, v := range other.Elements() {
    if !set.Contains(v) {//只要set中有一個包含other中的數據,就返回false
      return false
    }
  }
  return true
}

集合的運算包括并集、交集、差集對稱差集

并集運算是指把兩個集合中的所有元素都合并起來并組合成一個集合。

交集運算是指找到兩個集合中共有的元素并把它們組成一個集合。

集合 A集合 B 進行差集運算的含義是找到只存在于集合 A 中但不存在于集合 B 中的元素并把它們組成一個集合。

對稱差集運算與差集運算類似但有所區別。對稱差集運算是指找到只存在于集合 A 中但不存在于集合 B 中的元素,再找到只存在于集合 B 中但不存在于集合 A 中的元素,最后把它們合并起來并組成一個集合。

實現并集運算

// 生成集合 set 和集合 other 的并集
func (set *HashSet) Union(other *HashSet) *HashSet {
  if set == nil || other == nil {// set和other都為nil,則它們的并集為nil
    return nil
  }
  unionedSet := NewHashSet()//新創建一個HashSet類型值,它的長度為0,即元素數量為0
  for _, v := range set.Elements() {//將set中的元素添加到unionedSet中
    unionedSet.Add(v)
  }
  if other.Len() == 0 {
    return unionedSet
  }
  for _, v := range other.Elements() {//將other中的元素添加到unionedSet中,如果遇到相同,則不添加(在Add方法邏輯中體現)
    unionedSet.Add(v)
  }
  return unionedSet
}

實現交集運算

// 生成集合 set 和集合 other 的交集
func (set *HashSet) Intersect(other *HashSet) *HashSet {
  if set == nil || other == nil {// set和other都為nil,則它們的交集為nil
    return nil
  }
  intersectedSet := NewHashSet()//新創建一個HashSet類型值,它的長度為0,即元素數量為0
  if other.Len() == 0 {//other的元素數量為0,直接返回intersectedSet
    return intersectedSet
  }
  if set.Len()  other.Len() {//set的元素數量少于other的元素數量
    for _, v := range set.Elements() {//遍歷set
      if other.Contains(v) {//只要將set和other共有的添加到intersectedSet
        intersectedSet.Add(v)
      }
    }
  } else {//set的元素數量多于other的元素數量
    for _, v := range other.Elements() {//遍歷other
      if set.Contains(v) {//只要將set和other共有的添加到intersectedSet
        intersectedSet.Add(v)
      }
    }
  }
  return intersectedSet
}

差集

// 生成集合 set 對集合 other 的差集
func (set *HashSet) Difference(other *HashSet) *HashSet {
  if set == nil || other == nil {// set和other都為nil,則它們的差集為nil
    return nil
  }
  differencedSet := NewHashSet()//新創建一個HashSet類型值,它的長度為0,即元素數量為0
  if other.Len() == 0 { // 如果other的元素數量為0
    for _, v := range set.Elements() {//遍歷set,并將set中的元素v添加到differencedSet
      differencedSet.Add(v)
    }
    return differencedSet//直接返回differencedSet
  }
  for _, v := range set.Elements() {//other的元素數量不為0,遍歷set
    if !other.Contains(v) {//如果other中不包含v,就將v添加到differencedSet中
      differencedSet.Add(v)
    }
  }
  return differencedSet
}

對稱差集

// 生成集合 one 和集合 other 的對稱差集
func (set *HashSet) SymmetricDifference(other *HashSet) *HashSet {
  if set == nil || other == nil {// set和other都為nil,則它們的對稱差集為nil
    return nil
  }
  diffA := set.Difference(other)//生成集合 set 對集合 other 的差集
  if other.Len() == 0 {//如果other的元素數量等于0,那么other對集合set的差集為空,則直接返回diffA
    return diffA
  }
  diffB := other.Difference(set)//生成集合 other 對集合 set 的差集
  return diffA.Union(diffB)//返回集合 diffA 和集合 diffB 的并集
}

4.進一步重構
目前所實現的 HashSet 類型提供了一些必要的集合操作功能,但是不同應用場景下可能會需要使用功能更加豐富的集合類型。當有多個集合類型的時候,應該在它們之上抽取出一個接口類型以標識它們共有的行為方式。依據 HashSet 類型的聲明,可以如下聲明 Set 接口類型:

type Set interface {
  Add(e interface{}) bool
  Remove(e interface{})
  Clear()
  Contains(e interface{}) bool
  Len() int
  Same(other Set) bool
  Elements() []interface{}
  String() string
}

注意: Set 中的 Same 方法的簽名與附屬于 HashSet類型的 Same 方法有所不同。這里不能再接口類型的方法的簽名中包含它的實現類型。因此這里的改動如下:

func (set *HashSet) Same(other Set) bool {
  //省略若干語句
}

修改了 Same 方法的簽名,目的是讓 *HashSet 類型成為 Set 接口類型的一個實現類型。

高級功能的方法應該適用于所有的實現類型,完全可以抽離出成為獨立的函數。并且,也不應該在每個實現類型中重復地實現這些高級方法。如下為改造后的 IsSuperset 方法的聲明:

// 判斷集合 one 是否是集合 other 的超集
// 讀者應重點關注IsSuperset與附屬于HashSet類型的IsSuperset方法的區別
func IsSuperset(one Set, other Set) bool {
  if one == nil || other == nil {
    return false
  }
  oneLen := one.Len()
  otherLen := other.Len()
  if oneLen == 0 || oneLen == otherLen {
    return false
  }
  if oneLen > 0  otherLen == 0 {
    return true
  }
  for _, v := range other.Elements() {
    if !one.Contains(v) {
      return false
    }
  }
  return true
}

以上就是Go語言之自定義集合Set的全部內容,希望對大家學習Go語言有所幫助。

您可能感興趣的文章:
  • Golang中的自定義函數詳解
  • golang對自定義類型進行排序的解決方法
  • goLang引入自定義包的方法

標簽:七臺河 宜昌 眉山 邢臺 紹興 上海 盤錦 雅安

巨人網絡通訊聲明:本文標題《Go語言之自定義集合Set》,本文關鍵詞  語,言之,自定義,集合,Set,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Go語言之自定義集合Set》相關的同類信息!
  • 本頁收集關于Go語言之自定義集合Set的相關信息資訊供網民參考!
  • 推薦文章
    欧美中文字幕一区| 日韩精品中文字幕久久臀| 国产精品免费av一区二区| 日本特黄a级片| 最新欧美日韩亚洲| 午夜精品一区二区三区在线| 粉嫩嫩av羞羞动漫久久久| www.四虎精品| 亚洲一区二区三| 美女视频网站久久| 在线免费黄色小视频| 激情内射人妻1区2区3区| 国产成人免费av电影| 亚洲v中文字幕| 日本熟妇毛耸耸xxxxxx| 九九九九久久久久| 亚洲女在线观看| 亚洲视频一二区| 精品一区二区在线视频| 国产美女视频免费| 国产91在线播放九色快色| 日韩视频不卡中文| 欧美午夜精品久久久久久孕妇| 欧美三级蜜桃2在线观看| 日本大香伊一区二区三区| 中文字幕人成不卡一区| 国产又大又粗又硬| 1024精品视频| 日韩在线观看免费高清| 亚洲女人的天堂| 在线观看黄网站| 亚洲人成人77777线观看| 欧美美女操人视频| 久久久久久久久久久av| 精品女厕一区二区三区| 国产成人精品综合在线观看| 88av在线视频| 欧美激情一级欧美精品| 亚洲国产日韩欧美在线99| 精品久久久久久中文字幕一区奶水 | 久久精品国产亚洲AV无码男同| 国产老头老太做爰视频| 国产三级国产精品国产国在线观看| 日本精品久久久久久久久久| 理论片在线不卡免费观看| 欧洲一区二区三区在线| 国产女同互慰高潮91漫画| 长河落日免费高清观看| 99在线热播| 欧美极品在线视频| 91免费视频网站| 精品剧情在线观看| 色94色欧美sute亚洲线路一久 | 欧美三级韩国三级日本三斤| 成人午夜电影小说| 一本一道精品欧美中文字幕| 国产成人免费看一级大黄| 久久狠狠婷婷| 国产精品一级黄| 欧美极品aⅴ影院| 日本韩国精品一区二区在线观看| gogogo免费视频观看亚洲一| 蜜桃伊人久久| 久久精品网站免费观看| 国产伦理在线观看| 欧美福利在线视频| 国产免费中文字幕| 成人免费看片视频在线观看| 91在线网站视频| 久久久人成影片一区二区三区观看| 亚洲第一精品夜夜躁人人爽| 国产精品123区| 中日韩黄色大片| 久久精品天堂| 久久久天天操| 日本激情一区二区| 在线看黄色的网站| 欧美乱妇40p| 亚洲欧洲一区二区三区久久| 日韩激情av在线免费观看| 欧美极品少妇全裸体| 日日骚一区二区网站| 欧美 日本 亚洲| youjizz亚洲女人| 亚欧精品在线视频| 一区二区三区在线观看www| 久久青青草原| 免费av在线一区二区| 97人摸人人澡人人人超一碰| 日韩写真欧美这视频| 欧美日韩一本到| 欧美国产日韩一区二区三区| 97免费在线视频| 国内免费久久久久久久久久久| 久久精品视频导航| 色综合久久久久网| 日韩精品免费一线在线观看| 久久天天躁夜夜躁狠狠躁2022| 99在线国产| 久久6免费视频| 二区三区四区视频| 一级免费在线观看| 久久久久黄色片| 国产精品视频一区二区三| 国产人妻人伦精品1国产丝袜 | 美女又爽又黄视频毛茸茸| 日本不卡二区高清三区| 欧美成人免费在线视频| 欧美在线观看视频一区二区三区| 91麻豆精品国产91久久久使用方法| 精品粉嫩aⅴ一区二区三区四区| 亚洲欧美视频一区| 日本高清成人免费播放| 一区二区三区www| 色阁综合av| 中国xxxx性xxxx产国| 国产精品一区二区三区99| 国产精品你懂的| 亚洲色图第三页| 91九色国产社区在线观看| 亚洲精品欧美极品| 亚洲视频电影图片偷拍一区| 日韩有码视频在线| 81精品国产乱码久久久久久| 亚洲精品久久久久久下一站| 亚洲免费中文字幕| 日本a级片久久久| 亚洲最大成人网站| 国产91美女视频| 欧美一级小视频| 久久青青草视频| 亚洲男人在线天堂| 日韩久久精品视频| 亚洲女同志亚洲女同女播放| 亚洲激情自拍偷拍| 日韩在线欧美在线国产在线| 精品国一区二区三区| 亚洲第一男人av| 亚洲国产精品小视频| 久久精品视频免费播放| 91亚洲人电影| 久久这里只有精品8| 国产精品手机视频| 91在线在线观看| 97av自拍| 国产精品视频500部| 精品久久久噜噜噜噜久久图片| 一级片黄色录像| 免费在线不卡视频| 高清免费成人av| 欧美一a一片一级一片| 97久久久免费福利网址| 可以在线看的黄色网址| 一区二区三区四区影院| 黑人巨大精品欧美| 日本在线观看中文字幕| 青娱乐精品视频在线| 亚洲一区二区三区在线| 国产视频一区二区在线| 久久一日本道色综合| 国产精品久久久久一区二区三区共| 日韩理论片在线| 日韩欧美一区二区三区| 国产日韩欧美电影在线观看| 国产成人精品无码播放| 欧美激情图片小说| 国产福利91精品一区| 欧美日韩午夜在线| 国产热re99久久6国产精品| 日韩精品aaa| 97成人资源站| 中文字幕有码无码人妻av蜜桃| 91丨九色丨蝌蚪丨老版| 日韩午夜中文字幕| 在线精品高清中文字幕| 久久精品国产2020观看福利| 综合色婷婷一区二区亚洲欧美国产| 99久久精品日本一区二区免费 | 丁香婷婷综合色啪| 精品免费国产一区二区三区四区| 日韩一区二区免费电影| 538国产精品视频一区二区| 精品人妻一区二区免费| 国产盗摄女厕一区二区三区| 91精品久久久久久久久久入口 | 国产精品一区二区三区精品| 可以免费看的av毛片| 日韩丝袜美女视频| 在线观看av的网址| 国产精品一区二区三区在线免费观看 | 日韩在线不卡av| 国产婷婷色一区二区三区| 亚洲人成网站在线播| 欧美一级淫片丝袜脚交| 亚洲一区二区三区涩| 久久九九国产| 乱亲女秽乱长久久久| 综合久久国产| 91亚洲欧美激情| 欧美日韩精品专区| 国产mv久久久| 一本色道久久综合亚洲二区三区 | 免费在线观看日韩视频| 日本一二区免费| 欧美日韩一级大片| 老牛嫩草一区二区三区日本| 久久久久国产免费免费| 7777精品伊人久久久大香线蕉经典版下载 | 一道本在线观看视频| 中文字幕网av| 亚洲第一在线播放| 亚洲欧美日韩国产一区二区三区| 美女福利精品视频| 色999五月色| 色婷婷av一区二区三区软件| 一道本在线观看视频| 粉嫩高清一区二区三区精品视频 | 中文在线免费观看| 日韩精品成人一区二区在线| 日韩中文字幕视频在线观看| 久草综合在线观看| 亚洲av成人无码网天堂| 精品久久久久久亚洲综合网| 日本婷婷久久久久久久久一区二区| 国产乱色精品成人免费视频| 色老头一区二区三区在线观看| 日韩国产小视频| 免费黄色一级大片| 国产丝袜一区二区三区| 五十路熟女丰满大屁股| 亚洲色图欧美视频| 日韩一级片网站| 国产精品久久在线观看| 91福利免费观看| 日韩一级片免费观看| 日本高清视频一区二区| 国产亚洲精品自在久久| 日韩av电影天堂| 午夜精品一区二区三区在线视频| 菠萝菠萝蜜网站| 亚洲婷婷在线视频| 伊人情人网综合| 日韩福利电影在线| 日本久久久网站| 欧美久久久久久久久中文字幕| 国产精品三区在线观看| 日韩精品免费综合视频在线播放| 日本少妇高潮喷水xxxxxxx| 亚洲成人av电影| 九九精品视频在线| 人妻少妇一区二区| 亚洲超碰97人人做人人爱| 欧美亚洲一二三区| 日韩二区三区在线观看| 国产成人精品久久二区二区91| 日韩在线观看视频一区二区| 亚洲爱爱爱爱爱| 欧美激情第四页| 亚洲欧美一区二区三| 国产一区二区三区在线| 老司机久久精品| 成人18精品视频| 热re91久久精品国99热蜜臀| 国产亚洲久一区二区| 国产精品中文久久久久久久| 日韩国产欧美在线视频| 欧美又大又粗又长| 手机在线精品视频| 国产精品久久久久久久久久小说 | 国产亚洲一区二区在线| 亚洲免费一级片| 性欧美xxxx| www.xxxx日本| 欧美一区日韩一区| 一区二区三区视频在线观看免费| 久久你懂得1024| 日本福利视频一区| 色老综合老女人久久久| 这里只有久久精品| 日韩亚洲国产中文字幕欧美| 黄色av免费观看| 精品人妻无码一区二区色欲产成人| 日本激情一区二区| 国产精品性做久久久久久| 日本一区二区三区视频视频| 亚洲第一久久影院| 日韩一级二级三级| 日韩在线免费观看视频| 国产精品第3页| 欧美激情专区| 国产女大学生av| 在线播放第一页| 欧美日韩大片在线观看| 国产毛片毛片毛片毛片| 国产在线精品不卡| 国产精品午夜在线| 欧美色网一区二区| 中文字幕亚洲欧美在线| 国产精品久久久久久久美男| 欧美在线视频二区| 无人在线观看的免费高清视频| 国精产品一区一区三区免费视频| 日韩免费在线视频观看| 四季av日韩精品一区| 成人免费毛片aaaaa**| 性久久久久久久久久久久| 日韩电影中文字幕在线观看| 日本三级久久久| 欧美一区二区影视| 欧美男女交配视频| 婷婷伊人五月天| 亚洲av无码国产精品永久一区| 成人激情校园春色| 欧美性xxxx极品高清hd直播| 国产香蕉97碰碰久久人人| 国产精品成av人在线视午夜片| 日韩中文字幕一区| www.偷拍.com| 国产又黄又粗又爽| 精品一区二区三区久久| 一区二区三区日韩欧美精品| 亚洲国产日韩欧美在线动漫| 日本欧美一级片| 亚洲一区二区在线观| 18深夜在线观看免费视频| 亚洲精品国产精品乱码| 精一区二区三区| 五月综合激情网| 日韩在线视频一区| 国产女人水真多18毛片18精品 | 久久综合九色综合97婷婷 | 97视频久久久| 成人午夜福利一区二区| 国产精品久久久久久免费免熟| 成人免费高清在线观看| 欧美羞羞免费网站| 久久久久国产精品免费| 日韩欧美三级一区二区| 蜜臀视频在线观看| 中文字幕av影视| 91小视频在线| 日韩一级二级三级精品视频| 国产精品视频不卡| 国产美女三级视频| 久久久久香蕉视频| 国内外成人在线视频| 在线日韩av片| 欧美亚洲在线观看| 少妇大叫太大太粗太爽了a片小说| 香蕉视频久久久| 亚洲AV成人无码一二三区在线| 亚洲图片欧美视频| 欧美成人在线网站| 亚洲激情一区二区| 中文字幕免费高清| 天堂资源在线中文精品| 丁香五六月婷婷久久激情| 久久久久国产视频| 六月婷婷激情综合| 神马午夜精品91| 国产一区二区三区香蕉| 7777精品伊人久久久大香线蕉 | 欧美日韩一区不卡| 国产成人拍精品视频午夜网站| jizzjizz国产精品喷水| 国产一级片久久| www.在线成人| 精品一区二区三区电影| 精品一区日韩成人| 黄色短视频在线观看| 亚洲欧美自偷自拍| 欧美影院一区二区| 国产一区二区色| 搡的我好爽在线观看免费视频| 国产永久免费视频| 亚洲综合丝袜美腿| 欧美精品xxx| 国产男女激情视频| 一本色道久久综合无码人妻| 一区二区三区在线视频免费| 久久久免费在线观看| 黑森林福利视频导航| 中文字幕在线视频免费| 亚洲另类色综合网站| 久久久久国色av免费观看性色| 国产美女三级视频| 国产手机视频在线| 欧美日韩一区二区在线播放| 国产精品av网站| 杨幂一区二区国产精品| 久久久久久黄| 欧美精三区欧美精三区| 痴汉一区二区三区| 亚洲а∨天堂久久精品2021| 国产成人超碰人人澡人人澡| 日韩成人在线播放| 在线观看福利一区| 国产一区二区三区影院| 国产精品免费看片| 81精品国产乱码久久久久久| 中文字幕在线观看日 | 亚洲国产高清不卡| 欧美精品18videos性欧| 国产一区视频免费观看| 亚洲av无码国产精品永久一区| 日本高清无吗v一区| 狠狠色伊人亚洲综合网站色| 亚洲 欧美 变态 另类 综合| 国产片一区二区三区| 91精品国产高清久久久久久91|