精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java數據結構與算法解析(八)——伸展樹

開發 后端 大數據 算法
伸展樹(Splay Tree)是特殊的二叉查找樹。它的特殊是指,它除了本身是棵二叉查找樹之外,它還具備一個特點: 當某個節點被訪問時,伸展樹會通過旋轉使該節點成為樹根。這樣做的好處是,下次要訪問該節點時,能夠迅速的訪問到該節點。

Java數據結構與算法解析(八)——伸展樹

伸展樹簡介

伸展樹(Splay Tree)是特殊的二叉查找樹。

它的特殊是指,它除了本身是棵二叉查找樹之外,它還具備一個特點: 當某個節點被訪問時,伸展樹會通過旋轉使該節點成為樹根。這樣做的好處是,下次要訪問該節點時,能夠迅速的訪問到該節點。

特性

  1. 和普通的二叉查找樹相比,具有任何情況下、任何操作的平攤O(log2n)的復雜度,時間性能上更好
  2. 和一般的平衡二叉樹比如 紅黑樹、AVL樹相比,維護更少的節點額外信息,空間性能更優,同時編程復雜度更低
  3. 在很多情況下,對于查找操作,后面的查詢和之前的查詢有很大的相關性。這樣每次查詢操作將被查到的節點旋轉到樹的根節點位置,這樣下次查詢操作可以很快的完成
  4. 可以完成對區間的查詢、修改、刪除等操作,可以實現線段樹和樹狀數組的所有功能

旋轉

伸展樹實現O(log2n)量級的平攤復雜度依靠每次對伸展樹進行查詢、修改、刪除操作之后,都進行旋轉操作 Splay(x, root),該操作將節點x旋轉到樹的根部。

伸展樹的旋轉有六種類型,如果去掉鏡像的重復,則為三種:zig(zag)、zig-zig(zag-zag)、zig-zag(zag-zig)。

1 自底向上的方式進行旋轉

1.1 zig旋轉

 

如圖所示,x節點的父節點為y,x為y的左子節點,且y節點為根。則只需要對x節點進行一次右旋(zig操作),使之成為y的父節點,就可以使x成為伸展樹的根節點。

1.2 zig-zig旋轉

 

如上圖所示,x節點的父節點y,y的父節點z,三者在一字型鏈上。此時,先對y節點和z節點進行zig旋轉,然后再對x節點和y節點進行zig旋轉,最后變為右圖所示,x成為y和z的祖先節點。

1.3 zig-zag旋轉

 

如上圖所示,x節點的父節點y,y的父節點z,三者在之字型鏈上。此時,先對x節點和y節點進行zig旋轉,然后再對x節點和y節點進行zag旋轉,最后變為右圖所示,x成為y和z的祖先節點。

2 自頂向下的方式進行旋轉

這種方式不需要節點存儲其父節點的引用。當我們沿著樹向下搜索某個節點x時,將搜索路徑上的節點及其子樹移走。構建兩棵臨時的樹——左樹和右樹。沒有被移走的節點構成的樹稱為中樹。

  1. 當前節點x是中樹的根
  2. 左樹L保存小于x的節點
  3. 右樹R保存大于x的節點

開始時候,x是樹T的根,左樹L和右樹R都為空。三種旋轉操作:

2.1 zig旋轉

 

如圖所示,x節點的子節點y就是我們要找的節點,則只需要對y節點進行一次右旋(zig操作),使之成為x的父節點,就可以使y成為伸展樹的根節點。將y作為中樹的根,同時,x節點移動到右樹R中,顯然右樹上的節點都大于所要查找的節點。

2.2 zig-zig旋轉

 

如上圖所示,x節點的左子節點y,y的左子節點z,三者在一字型鏈上,且要查找的節點位于z節點為根的子樹中。此時,對x節點和y節點進行zig,然后對z和y進行zig,使z成為中樹的根,同時將y及其子樹掛載到右樹R上。

2.3 zig-zag旋轉

  

如上圖所示,x節點的左子節點y,y的右子節點z,三者在之字型鏈上,且需要查找的元素位于以z為根的子樹上。此時,先對x節點和y節點進行zig旋轉,將x及其右子樹掛載到右樹R上,此時y成為中樹的根節點;然后再對z節點和y節點進行zag旋轉,使得z成為中樹的根節點。

2.4 合并

 

最后,找到節點或者遇到空節點之后,需要對左、中、右樹進行合并。如圖所示,將左樹掛載到中樹的最左下方(滿足遍歷順序要求),將右樹掛載到中樹的最右下方(滿足遍歷順序要求)。

伸展樹的實現

1.節點

  1. public class SplayTree<T extends Comparable<T>> { 
  2.     private SplayTreeNode<T> mRoot;    // 根結點 
  3.  
  4.     public class SplayTreeNode<T extends Comparable<T>> { 
  5.         T key;                // 關鍵字(鍵值) 
  6.         SplayTreeNode<T> left;    // 左孩子 
  7.         SplayTreeNode<T> right;    // 右孩子 
  8.  
  9.         public SplayTreeNode() { 
  10.             this.left = null
  11.             this.right = null
  12.         } 
  13.  
  14.         public SplayTreeNode(T key, SplayTreeNode<T> left, SplayTreeNode<T> right) { 
  15.             this.key = key
  16.             this.left = left
  17.             this.right = right
  18.         } 
  19.     } 
  20.  

SplayTree是伸展樹,而SplayTreeNode是伸展樹節點。在此,我將SplayTreeNode定義為SplayTree的內部類。在伸展樹SplayTree中包含了伸展樹的根節點mRoot。SplayTreeNode包括的幾個組成元素:

  1. key – 是關鍵字,是用來對伸展樹的節點進行排序的。
  2. left – 是左孩子。
  3. right – 是右孩子。

2.旋轉

  1. /* 
  2. * 旋轉key對應的節點為根節點,并返回根節點。 
  3. * 注意: 
  4. *   (a):伸展樹中存在"鍵值為key的節點"。 
  5. *          將"鍵值為key的節點"旋轉為根節點。 
  6. *   (b):伸展樹中不存在"鍵值為key的節點",并且key < tree.key。 
  7. *      b-1 "鍵值為key的節點"的前驅節點存在的話,將"鍵值為key的節點"的前驅節點旋轉為根節點。 
  8. *      b-2 "鍵值為key的節點"的前驅節點存在的話,則意味著,key比樹中任何鍵值都小,那么此時,將最小節點旋轉為根節點。 
  9. *   (c):伸展樹中不存在"鍵值為key的節點",并且key > tree.key。 
  10. *      c-1 "鍵值為key的節點"的后繼節點存在的話,將"鍵值為key的節點"的后繼節點旋轉為根節點。 
  11. *      c-2 "鍵值為key的節點"的后繼節點不存在的話,則意味著,key比樹中任何鍵值都大,那么此時,將最大節點旋轉為根節點。 
  12. */ 
  13.    private SplayTreeNode<T> splay(SplayTreeNode<T> tree, T key) { 
  14.        if (tree == null
  15.            return tree; 
  16.  
  17.        SplayTreeNode<T> N = new SplayTreeNode<T>(); 
  18.        SplayTreeNode<T> l = N; 
  19.        SplayTreeNode<T> r = N; 
  20.        SplayTreeNode<T> c; 
  21.  
  22.        for (; ; ) { 
  23.            int cmp = key.compareTo(tree.key); 
  24.            if (cmp < 0) { 
  25.                if (key.compareTo(tree.left.key) < 0) { 
  26.                    c = tree.left;                           /* rotate right */ 
  27.                    tree.left = c.right
  28.                    c.right = tree; 
  29.                    tree = c; 
  30.                    if (tree.left == null
  31.                        break; 
  32.                } 
  33.                r.left = tree;                               /* link right */ 
  34.                r = tree; 
  35.                tree = tree.left
  36.            } else if (cmp > 0) { 
  37.  
  38.                if (tree.right == null
  39.                    break; 
  40.  
  41.                if (key.compareTo(tree.right.key) > 0) { 
  42.                    c = tree.right;                          /* rotate left */ 
  43.                    tree.right = c.left
  44.                    c.left = tree; 
  45.                    tree = c; 
  46.                    if (tree.right == null
  47.                        break; 
  48.                } 
  49.  
  50.                l.right = tree;                              /* link left */ 
  51.                l = tree; 
  52.                tree = tree.right
  53.            } else { 
  54.                break; 
  55.            } 
  56.        } 
  57.        l.right = tree.left;                                /* assemble */ 
  58.        r.left = tree.right
  59.        tree.left = N.right
  60.        tree.right = N.left
  61.  
  62.        return tree; 
  63.    } 
  64.  
  65.    public void splay(T key) { 
  66.        mRoot = splay(mRoot, key); 
  67.    }  

上面的代碼的作用:將”鍵值為key的節點”旋轉為根節點,并返回根節點。它的處理情況共包括:

(a):伸展樹中存在”鍵值為key的節點”。

將”鍵值為key的節點”旋轉為根節點。

(b):伸展樹中不存在”鍵值為key的節點”,并且key < tree->key。

b-1) “鍵值為key的節點”的前驅節點存在的話,將”鍵值為key的節點”的前驅節點旋轉為根節點。

b-2) “鍵值為key的節點”的前驅節點存在的話,則意味著,key比樹中任何鍵值都小,那么此時,將最小節點旋轉為根節點。

(c):伸展樹中不存在”鍵值為key的節點”,并且key > tree->key。

c-1) “鍵值為key的節點”的后繼節點存在的話,將”鍵值為key的節點”的后繼節點旋轉為根節點。

c-2) “鍵值為key的節點”的后繼節點不存在的話,則意味著,key比樹中任何鍵值都大,那么此時,將最大節點旋轉為根節點。

下面列舉個例子分別對a進行說明。

在下面的伸展樹中查找10,,共包括”右旋” –> “右鏈接” –> “組合”這3步。

 

01, 右旋

對應代碼中的”rotate right”部分

 

02, 右鏈接

對應代碼中的”link right”部分

 

03.組合

對應代碼中的”assemble”部分

 

 

提示:如果在上面的伸展樹中查找”70”,則正好與”示例1”對稱,而對應的操作則分別是”rotate left”, “link left”和”assemble”。

其它的情況,例如”查找15是b-1的情況,查找5是b-2的情況”等等,這些都比較簡單,大家可以自己分析。

3.插入

  1. /** 
  2.      * 將結點插入到伸展樹中,并返回根節點 
  3.      * @param tree 伸展樹的根節點 
  4.      * @param z 插入的結點 
  5.      * @return 
  6.      */ 
  7.     private SplayTreeNode<T> insert(SplayTreeNode<T> tree, SplayTreeNode<T> z) { 
  8.         int cmp; 
  9.         SplayTreeNode<T> y = null
  10.         SplayTreeNode<T> x = tree; 
  11.  
  12.         // 查找z的插入位置 
  13.         while (x != null) { 
  14.             y = x; 
  15.             cmp = z.key.compareTo(x.key); 
  16.             if (cmp < 0) 
  17.                 x = x.left
  18.             else if (cmp > 0) 
  19.                 x = x.right
  20.             else { 
  21.                 System.out.printf("不允許插入相同節點(%d)!\n", z.key); 
  22.                 z = null
  23.                 return tree; 
  24.             } 
  25.         } 
  26.  
  27.         if (y == null
  28.             tree = z; 
  29.         else { 
  30.             cmp = z.key.compareTo(y.key); 
  31.             if (cmp < 0) 
  32.                 y.left = z; 
  33.             else 
  34.                 y.right = z; 
  35.         } 
  36.  
  37.         return tree; 
  38.     } 
  39.  
  40.     public void insert(T key) { 
  41.         SplayTreeNode<T> z = new SplayTreeNode<T>(keynullnull); 
  42.  
  43.         // 如果新建結點失敗,則返回。 
  44.         if ((z = new SplayTreeNode<T>(keynullnull)) == null
  45.             return
  46.  
  47.         // 插入節點 
  48.         mRoot = insert(mRoot, z); 
  49.         // 將節點(key)旋轉為根節點 
  50.         mRoot = splay(mRoot, key); 
  51.     }  

insert(key)是提供給外部的接口,它的作用是新建節點(節點的鍵值為key),并將節點插入到伸展樹中;然后,將該節點旋轉為根節點。

insert(tree, z)是內部接口,它的作用是將節點z插入到tree中。insert(tree, z)在將z插入到tree中時,僅僅只將tree當作是一棵二叉查找樹,而且不允許插入相同節點。

4.刪除

  1. /** 
  2.      *  
  3.      * @param tree 伸展樹 
  4.      * @param key 刪除的結點 
  5.      * @return 
  6.      */ 
  7.     private SplayTreeNode<T> remove(SplayTreeNode<T> tree, T key) { 
  8.         SplayTreeNode<T> x; 
  9.  
  10.         if (tree == null
  11.             return null
  12.  
  13.         // 查找鍵值為key的節點,找不到的話直接返回。 
  14.         if (search(tree, key) == null
  15.             return tree; 
  16.  
  17.         // 將key對應的節點旋轉為根節點。 
  18.         tree = splay(tree, key); 
  19.  
  20.         if (tree.left != null) { 
  21.             // 將"tree的前驅節點"旋轉為根節點 
  22.             x = splay(tree.leftkey); 
  23.             // 移除tree節點 
  24.             x.right = tree.right
  25.         } 
  26.         else 
  27.             x = tree.right
  28.  
  29.         tree = null
  30.  
  31.         return x; 
  32.     } 
  33.  
  34.     public void remove(T key) { 
  35.         mRoot = remove(mRoot, key); 
  36.     }  

remove(key)是外部接口,remove(tree, key)是內部接口。

remove(tree, key)的作用是:刪除伸展樹中鍵值為key的節點。

它會先在伸展樹中查找鍵值為key的節點。若沒有找到的話,則直接返回。若找到的話,則將該節點旋轉為根節點,然后再刪除該節點。

伸展樹實現完整代碼

  1. public class SplayTree<T extends Comparable<T>> {     
  2. private SplayTreeNode<T> mRoot;    // 根結點 
  3.  
  4.     public class SplayTreeNode<T extends Comparable<T>> { 
  5.         T key;                // 關鍵字(鍵值) 
  6.         SplayTreeNode<T> left;    // 左孩子 
  7.         SplayTreeNode<T> right;    // 右孩子 
  8.  
  9.         public SplayTreeNode() { 
  10.             this.left = null
  11.             this.right = null
  12.         } 
  13.  
  14.         public SplayTreeNode(T key, SplayTreeNode<T> left, SplayTreeNode<T> right) { 
  15.             this.key = key
  16.             this.left = left
  17.             this.right = right
  18.         } 
  19.     } 
  20.  
  21.     /* 
  22.  * 旋轉key對應的節點為根節點,并返回根節點。 
  23.  * 
  24.  * 注意: 
  25.  *   (a):伸展樹中存在"鍵值為key的節點"。 
  26.  *          將"鍵值為key的節點"旋轉為根節點。 
  27.  *   (b):伸展樹中不存在"鍵值為key的節點",并且key < tree.key。 
  28.  *      b-1 "鍵值為key的節點"的前驅節點存在的話,將"鍵值為key的節點"的前驅節點旋轉為根節點。 
  29.  *      b-2 "鍵值為key的節點"的前驅節點存在的話,則意味著,key比樹中任何鍵值都小,那么此時,將最小節點旋轉為根節點。 
  30.  *   (c):伸展樹中不存在"鍵值為key的節點",并且key > tree.key。 
  31.  *      c-1 "鍵值為key的節點"的后繼節點存在的話,將"鍵值為key的節點"的后繼節點旋轉為根節點。 
  32.  *      c-2 "鍵值為key的節點"的后繼節點不存在的話,則意味著,key比樹中任何鍵值都大,那么此時,將最大節點旋轉為根節點。 
  33.  */ 
  34.     private SplayTreeNode<T> splay(SplayTreeNode<T> tree, T key) { 
  35.         if (tree == null
  36.             return tree; 
  37.  
  38.         SplayTreeNode<T> N = new SplayTreeNode<T>(); 
  39.         SplayTreeNode<T> l = N; 
  40.         SplayTreeNode<T> r = N; 
  41.         SplayTreeNode<T> c; 
  42.  
  43.         for (; ; ) { 
  44.             int cmp = key.compareTo(tree.key); 
  45.             if (cmp < 0) { 
  46.                 if (key.compareTo(tree.left.key) < 0) { 
  47.                     c = tree.left;                           /* rotate right */ 
  48.                     tree.left = c.right
  49.                     c.right = tree; 
  50.                     tree = c; 
  51.                     if (tree.left == null
  52.                         break; 
  53.                 } 
  54.                 r.left = tree;                               /* link right */ 
  55.                 r = tree; 
  56.                 tree = tree.left
  57.             } else if (cmp > 0) { 
  58.  
  59.                 if (tree.right == null
  60.                     break; 
  61.  
  62.                 if (key.compareTo(tree.right.key) > 0) { 
  63.                     c = tree.right;                          /* rotate left */ 
  64.                     tree.right = c.left
  65.                     c.left = tree; 
  66.                     tree = c; 
  67.                     if (tree.right == null
  68.                         break; 
  69.                 } 
  70.  
  71.                 l.right = tree;                              /* link left */ 
  72.                 l = tree; 
  73.                 tree = tree.right
  74.             } else { 
  75.                 break; 
  76.             } 
  77.         } 
  78.         l.right = tree.left;                                /* assemble */ 
  79.         r.left = tree.right
  80.         tree.left = N.right
  81.         tree.right = N.left
  82.  
  83.         return tree; 
  84.     } 
  85.  
  86.     public void splay(T key) { 
  87.         mRoot = splay(mRoot, key); 
  88.     } 
  89.  
  90.  
  91.  
  92.     /** 
  93.      * 將結點插入到伸展樹中,并返回根節點 
  94.      * @param tree 伸展樹的根節點 
  95.      * @param z 插入的結點 
  96.      * @return 
  97.      */ 
  98.     private SplayTreeNode<T> insert(SplayTreeNode<T> tree, SplayTreeNode<T> z) { 
  99.         int cmp; 
  100.         SplayTreeNode<T> y = null
  101.         SplayTreeNode<T> x = tree; 
  102.  
  103.         // 查找z的插入位置 
  104.         while (x != null) { 
  105.             y = x; 
  106.             cmp = z.key.compareTo(x.key); 
  107.             if (cmp < 0) 
  108.                 x = x.left
  109.             else if (cmp > 0) 
  110.                 x = x.right
  111.             else { 
  112.                 System.out.printf("不允許插入相同節點(%d)!\n", z.key); 
  113.                 z = null
  114.                 return tree; 
  115.             } 
  116.         } 
  117.  
  118.         if (y == null
  119.             tree = z; 
  120.         else { 
  121.             cmp = z.key.compareTo(y.key); 
  122.             if (cmp < 0) 
  123.                 y.left = z; 
  124.             else 
  125.                 y.right = z; 
  126.         } 
  127.  
  128.         return tree; 
  129.     } 
  130.  
  131.     public void insert(T key) { 
  132.         SplayTreeNode<T> z = new SplayTreeNode<T>(keynullnull); 
  133.  
  134.         // 如果新建結點失敗,則返回。 
  135.         if ((z = new SplayTreeNode<T>(keynullnull)) == null
  136.             return
  137.  
  138.         // 插入節點 
  139.         mRoot = insert(mRoot, z); 
  140.         // 將節點(key)旋轉為根節點 
  141.         mRoot = splay(mRoot, key); 
  142.     } 
  143.  
  144.     /* 
  145.  * 刪除結點(z),并返回被刪除的結點 
  146.  * 
  147.  * 參數說明: 
  148.  *     bst 伸展樹 
  149.  *     z 刪除的結點 
  150.  */ 
  151.  
  152.     /** 
  153.      * 
  154.      * @param tree 伸展樹 
  155.      * @param key 刪除的結點 
  156.      * @return 
  157.      */ 
  158.     private SplayTreeNode<T> remove(SplayTreeNode<T> tree, T key) { 
  159.         SplayTreeNode<T> x; 
  160.  
  161.         if (tree == null
  162.             return null
  163.  
  164.         // 查找鍵值為key的節點,找不到的話直接返回。 
  165.         if (search(tree, key) == null
  166.             return tree; 
  167.  
  168.         // 將key對應的節點旋轉為根節點。 
  169.         tree = splay(tree, key); 
  170.  
  171.         if (tree.left != null) { 
  172.             // 將"tree的前驅節點"旋轉為根節點 
  173.             x = splay(tree.leftkey); 
  174.             // 移除tree節點 
  175.             x.right = tree.right
  176.         } 
  177.         else 
  178.             x = tree.right
  179.  
  180.         tree = null
  181.  
  182.         return x; 
  183.     } 
  184.  
  185.     public void remove(T key) { 
  186.         mRoot = remove(mRoot, key); 
  187.     } 
  188.  
  189.     /* 
  190.     * (遞歸實現)查找"伸展樹x"中鍵值為key的節點 
  191.     */ 
  192.     private SplayTreeNode<T> search(SplayTreeNode<T> x, T key) { 
  193.         if (x==null
  194.             return x; 
  195.  
  196.         int cmp = key.compareTo(x.key); 
  197.         if (cmp < 0) 
  198.             return search(x.leftkey); 
  199.         else if (cmp > 0) 
  200.             return search(x.rightkey); 
  201.         else 
  202.             return x; 
  203.     } 
  204.  
  205.     public SplayTreeNode<T> search(T key) { 
  206.         return search(mRoot, key); 
  207.     } 
  208.  
  209.     /* 
  210.    * 查找最小結點:返回tree為根結點的伸展樹的最小結點。 
  211.    */ 
  212.     private SplayTreeNode<T> minimum(SplayTreeNode<T> tree) { 
  213.         if (tree == null
  214.             return null
  215.  
  216.         while(tree.left != null
  217.             tree = tree.left
  218.         return tree; 
  219.     } 
  220.  
  221.     public T minimum() { 
  222.         SplayTreeNode<T> p = minimum(mRoot); 
  223.         if (p != null
  224.             return p.key
  225.  
  226.         return null
  227.     } 
  228.  
  229.     /* 
  230.      * 查找最大結點:返回tree為根結點的伸展樹的最大結點。 
  231.      */ 
  232.     private SplayTreeNode<T> maximum(SplayTreeNode<T> tree) { 
  233.         if (tree == null
  234.             return null
  235.  
  236.         while(tree.right != null
  237.             tree = tree.right
  238.         return tree; 
  239.     } 
  240.  
  241.     public T maximum() { 
  242.         SplayTreeNode<T> p = maximum(mRoot); 
  243.         if (p != null
  244.             return p.key
  245.  
  246.         return null
  247.     }  
責任編輯:龐桂玉 來源: 36大數據
相關推薦

2017-08-31 09:45:43

JavaArrayList數據

2022-09-26 07:56:53

AVL算法二叉樹

2021-03-18 08:44:20

Java數據結構算法

2022-09-21 07:57:33

二叉搜索樹排序二叉樹

2023-09-15 10:33:41

算法數據結構

2020-10-30 09:56:59

Trie樹之美

2021-04-07 09:26:37

Java數據結構算法

2021-03-24 10:41:04

Java數據結構算法

2020-10-21 14:57:04

數據結構算法圖形

2023-03-08 08:03:09

數據結構算法歸并排序

2023-10-27 07:04:20

2023-03-31 08:24:29

數據結構算法數目

2021-05-12 09:07:09

Java數據結構算法

2021-09-29 18:28:41

數據結構算法最小生成樹

2021-03-29 10:13:47

Java編程數據結構算法

2021-03-19 10:25:12

Java數據結構算法

2023-03-07 08:02:07

數據結構算法數列

2020-11-02 09:15:47

算法與數據結構

2021-04-13 09:37:41

Java數據結構算法

2021-03-09 06:30:32

JAVA數據結構算法
點贊
收藏

51CTO技術棧公眾號

欧美巨猛xxxx猛交黑人97人| 欧美日韩亚洲网| 亚洲va久久久噜噜噜| 免费人成年激情视频在线观看| 一区二区视频| 噜噜噜久久亚洲精品国产品小说| 亚洲天堂男人天堂| 黑人性生活视频| 亚洲精品日产| 1000精品久久久久久久久| 国产欧美日韩视频一区二区三区| 亚洲色成人www永久网站| 偷偷www综合久久久久久久| 亚洲成人中文字幕| 99日在线视频| a日韩av网址| 一区二区三区在线播放| 欧美日韩国产免费一区二区三区| 99视频免费看| 日韩一区二区在线| 精品福利二区三区| 亚洲欧美aaa| 一区二区精品伦理...| 中文字幕一区av| 欧美午夜精品久久久久久蜜| 成人av无码一区二区三区| 日韩精品午夜视频| 91精品国产91久久久久| 成人性生活毛片| 精品一区二区三区的国产在线观看| 日韩一级黄色大片| 污污的网站免费| 台湾佬成人网| 色哟哟一区二区在线观看| 日本男女交配视频| 亚洲精品一区二区三区蜜桃| 人人精品人人爱| 97成人精品区在线播放| 欧美黑人一级片| 水蜜桃精品av一区二区| 国产一级揄自揄精品视频| 少妇户外露出[11p]| 91成人噜噜噜在线播放| 欧美一级在线免费| 九九久久久久久| 男女啪啪999亚洲精品| 在线亚洲一区观看| 国产精品69页| 惠美惠精品网| 欧美网站在线观看| 国产免费毛卡片| 美女av在线免费看| 欧美日韩国产区| 久久久久久久中文| 天堂中文av在线资源库| 欧美日韩性视频| 黄色动漫在线免费看| 欧美aaaaa性bbbbb小妇| 精品福利樱桃av导航| 亚洲国产成人精品无码区99| 成人免费一区二区三区牛牛| 一二三四区精品视频| 中文精品无码中文字幕无码专区| 午夜激情在线| 亚洲国产sm捆绑调教视频| 精品成在人线av无码免费看| av资源新版天堂在线| 亚洲另类在线视频| 裸模一区二区三区免费| 日本人妖在线| 国产无一区二区| 亚洲美女搞黄| 五月婷婷狠狠干| 91蝌蚪国产九色| 欧洲一区二区日韩在线视频观看免费 | 日韩av大片在线观看| 亚洲深夜影院| 久久精品视频一| 波多野结衣视频播放| 国产毛片久久久| 亚洲视频在线观看| 99热这里只有精品4| 国产精品99一区二区三| 欧美猛男性生活免费| 日韩男人的天堂| 久久午夜精品一区二区| 国产精品亚洲综合天堂夜夜| 国内精品国产成人国产三级| 不卡一区中文字幕| 日韩精品一线二线三线| gogo在线观看| 欧美极品xxx| 久久精品国产99精品国产亚洲性色| 亚洲色偷精品一区二区三区| 欧美激情一区二区在线| 水蜜桃在线免费观看| yw视频在线观看| 亚洲女同ⅹxx女同tv| 99视频在线免费播放| 国产极品久久久久久久久波多结野 | 久久av综合网| 外国成人直播| 日韩一区二区三区在线| 国产精品亚洲无码| 重囗味另类老妇506070| 欧洲亚洲女同hd| 99国产精品久久久久99打野战| 丝袜亚洲另类丝袜在线| **亚洲第一综合导航网站| 日本1级在线| 一区二区三区四区不卡视频| 男人女人黄一级| 国产一区二区三区亚洲| y97精品国产97久久久久久| 好吊操这里只有精品| 国产在线视视频有精品| 欧美一级爽aaaaa大片| 免费在线观看av电影| 欧美日韩视频不卡| 免费看国产黄色片| 欧美wwwwww| 欧美成人免费播放| 中文字幕有码视频| 91一区二区在线观看| 国产经典久久久| 欧美成a人片免费观看久久五月天| 精品亚洲va在线va天堂资源站| 精品国产视频一区二区三区| 日本不卡123| 黑人另类av| 高h视频在线播放| 欧美一区二区三区性视频| 日本欧美一区二区三区不卡视频| 亚洲伦伦在线| 国产精品毛片va一区二区三区| 好了av在线| 欧美日韩一区二区三区不卡 | 都市激情久久| 欧美巨乳在线观看| 国产乱人乱偷精品视频| 国产精品灌醉下药二区| 久久婷婷综合色| av中文一区| 国产精品久久久久久搜索| 在线免费一级片| 国产天堂亚洲国产碰碰| 欧美 激情 在线| 青草综合视频| 中文字幕亚洲欧美日韩在线不卡| 99久久久免费精品 | www.桃色.com| 99精品美女| 亚洲a一级视频| www红色一片_亚洲成a人片在线观看_| 欧美人伦禁忌dvd放荡欲情| 午夜不卡福利视频| 99re久久最新地址获取| 国产日产欧美a一级在线| 99青草视频在线播放视| 欧美日韩免费不卡视频一区二区三区| 99久久99久久精品免费| 国产精品v欧美精品v日本精品动漫| 91精品国产免费久久久久久 | 99久热在线精品996热是什么| 成人免费毛片aaaaa**| 97超碰人人澡| 婷婷综合一区| 国产精品劲爆视频| 男人影院在线观看| 欧美va日韩va| 久久免费激情视频| 国产蜜臀97一区二区三区| 伊人网在线综合| 欧美福利网址| 精品一区二区日本| **在线精品| 日韩视频永久免费观看| www黄色在线观看| 精品欧美aⅴ在线网站| 日本理论中文字幕| 国产美女一区二区| 国产成人无码精品久久久性色| 久久91麻豆精品一区| 国产精品视频午夜| 日本小视频在线免费观看| 亚洲精品国产成人| 伊人网免费视频| 亚洲免费观看高清完整版在线| 秘密基地免费观看完整版中文| 午夜综合激情| 91久久精品一区二区别| 天堂电影一区| 久久久精品国产| 亚洲欧美日韩动漫| 欧美精品粉嫩高潮一区二区| 日本一区二区不卡在线| 中文字幕免费观看一区| 国产美女无遮挡网站| 成人羞羞网站入口免费| 成人做爰66片免费看网站| 久久91导航| 欧美激情中文网| 99久久国产免费| 欧美天天综合色影久久精品| 日韩成人短视频| 国产亚洲短视频| jjzz黄色片| 精品一区二区av| 男人天堂1024| 自由日本语亚洲人高潮| 日本免费一区二区三区| 99国产精品免费网站| 国产精品一区二区女厕厕| 国产色播av在线| 色综合色综合网色综合| 在线观看二区| 国产丝袜视频一区| 免费观看黄色av| 日韩欧美国产精品| 91 中文字幕| 欧美国产视频在线| 国产激情视频网站| 国产成人亚洲精品狼色在线| 视色视频在线观看| 日韩精品国产欧美| 九色自拍视频在线观看| 欧美日韩精品| 秋霞在线一区二区| 郴州新闻综合频道在线直播| 久久伦理网站| 欧美电影免费网站| 成人性生交xxxxx网站| 全球最大av网站久久| 国产成人精品优优av| 亚洲最新无码中文字幕久久| 高清欧美性猛交xxxx| 手机在线免费看av| 久久99青青精品免费观看| 九色porny在线| zzjj国产精品一区二区| 日本中文字幕在线观看| 色先锋资源久久综合5566| 一区二区的视频| 欧美手机在线视频| 中文字幕精品一区二区精| 日本精品一区二区三区高清 | 欧美剧情片在线观看| 亚洲男人天堂网址| 色就色 综合激情| 高清乱码免费看污| 在线亚洲+欧美+日本专区| 日韩精品一区不卡| 在线观看一区二区精品视频| 无码人妻久久一区二区三区| 91精品福利视频| 国产亚洲久一区二区| 欧美群妇大交群中文字幕| 亚洲中文字幕在线一区| 91精品在线观看入口| 亚洲风情第一页| 日韩成人激情视频| 美国一级片在线免费观看视频 | 巨胸大乳www视频免费观看| 91免费看片在线观看| 亚洲天堂久久新| 中文字幕免费不卡| 国产又粗又硬又长又爽| 亚洲精品ww久久久久久p站| 久草视频免费在线播放| 亚洲成av人片一区二区| 久久永久免费视频| 69堂国产成人免费视频| 亚洲AV无码精品自拍| 亚洲激情视频在线观看| 黄色在线免费观看大全| 日韩中文字幕视频在线| 日本在线观看大片免费视频| 欧洲午夜精品久久久| 美女久久久久久| 51蜜桃传媒精品一区二区| 精品欧美午夜寂寞影院| 亚洲va久久久噜噜噜久久狠狠| 亚洲成av人电影| www.av毛片| 日本aⅴ亚洲精品中文乱码| www.亚洲自拍| 91欧美一区二区| 在线观看免费黄色网址| 亚洲成av人片在线| 在线免费a视频| 亚洲国产精品推荐| 香港伦理在线| 2019中文字幕全在线观看| 欧美久久久网站| 狠狠色噜噜狠狠色综合久| 国产精品久久久久久久久妇女| 18黄暴禁片在线观看| 日韩成人午夜电影| 亚洲一二三四五| 国产精品毛片无遮挡高清| 国产成人无码精品久久久久| 欧美日韩国产三级| 亚洲欧美一区二区三| 久久精品视频亚洲| 偷拍视频一区二区三区| 国产91亚洲精品一区二区三区| 日本在线电影一区二区三区| 国产 日韩 欧美在线| 久久精品999| a毛片毛片av永久免费| 亚洲线精品一区二区三区八戒| 日批视频免费观看| 日韩大陆欧美高清视频区| 九七久久人人| 国产精品久久久久久一区二区| 国产精品久av福利在线观看| 吴梦梦av在线| 日本不卡高清视频| 九色porny自拍视频| 亚洲国产cao| 亚洲产国偷v产偷v自拍涩爱| 日韩在线欧美在线国产在线| 日韩不卡免费高清视频| 精品无人区一区二区三区| 国产一在线精品一区在线观看| 91国内在线播放| 国产人久久人人人人爽| 91精品国产综合久久久蜜臀九色| 日韩亚洲欧美一区| 成人在线观看亚洲| 国产在线精品播放| 日韩欧美综合| 黄色成人免费看| 国产日韩欧美精品一区| 三级视频在线观看| 亚洲第一精品夜夜躁人人躁| 暖暖在线中文免费日本| 亚洲最大福利视频| 在线精品小视频| 91小视频在线播放| 国产精品高清亚洲| 一级黄色免费看| 最近更新的2019中文字幕| 免费观看成人性生生活片| 麻豆亚洲一区| 玖玖视频精品| 超碰97人人干| 91久久精品网| 成年在线观看免费人视频| 国产精品极品美女在线观看免费| 红桃视频在线观看一区二区| 91av在线免费播放| 久久久久久免费网| 欧美国产一级片| 日韩亚洲综合在线| 国产aⅴ精品一区二区四区| 91久久精品一区二区别| 中文字幕一区二区三区乱码图片 | 国产欧美日韩亚州综合| 最近中文字幕av| 日韩三级成人av网| 永久免费精品视频| 九九爱精品视频| www国产亚洲精品久久麻豆| 亚洲图片欧美日韩| 色综久久综合桃花网| 国产剧情一区二区在线观看| 久久av高潮av| 91首页免费视频| 中文字幕 欧美激情| 美女啪啪无遮挡免费久久网站| 爱高潮www亚洲精品| 欧美激情成人网| 国产精品久线在线观看| 精品人妻一区二区三区换脸明星| 欧美精品久久久久久久| 亚洲婷婷丁香| 中文字幕在线观看日 | 深夜成人在线观看| 欧美影院视频| 国产在线青青草| 国产精品电影一区二区三区| 欧洲精品久久一区二区| 国产xxx69麻豆国语对白| 亚洲精品午夜av福利久久蜜桃| 在线观看免费视频黄| 欧美这里有精品| 日本中文字幕中出在线| 欧美中文娱乐网| 国产福利一区二区| 一级黄色大片视频| 欧美日韩成人黄色| 九九视频精品全部免费播放| 91aaa精品| 色婷婷综合五月| 日本片在线观看| 亚洲成人网上| 99热99精品| 日韩成年人视频| 日韩在线中文字幕|