精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

亚洲欧美另类小说| 欧美阿v一级看视频| 欧洲色大大久久| 日韩亚洲不卡在线| 国产精品一区二区免费视频| 人人狠狠综合久久亚洲婷| 欧美一区二区网站| 欧美三级午夜理伦三级老人| 成人免费视频国产| 免费在线亚洲欧美| 久久视频在线观看免费| 亚洲国产精品成人综合久久久| 日日夜夜天天综合| 一区二区三区欧美日韩| 蜜桃网站成人| www.桃色av嫩草.com| 蜜桃av一区| 久久国产加勒比精品无码| 免费a在线观看播放| 91精品一久久香蕉国产线看观看| 亚洲电影在线播放| 伊人天天久久大香线蕉av色| 头脑特工队2在线播放| 狠狠狠色丁香婷婷综合激情| 97人人爽人人喊人人模波多| 玖玖爱这里只有精品| 综合亚洲自拍| 日韩免费观看高清完整版| 精品久久久噜噜噜噜久久图片 | 美女脱光内衣内裤视频久久网站 | 唐人社导航福利精品| 一区二区三区.www| 一本久道久久综合狠狠爱亚洲精品| 欧美视频久久久| 久久成人羞羞网站| 茄子视频成人在线| 欧美日韩偷拍视频| 久久大综合网| 亚洲性猛交xxxxwww| 九色91porny| 亚洲成a人片777777久久| 色噜噜狠狠色综合欧洲selulu| 欧美精品久久久久久久自慰| 成人黄色在线电影| 中文字幕在线观看一区二区| 日韩av在线一区二区三区| 天堂a中文在线| 大桥未久av一区二区三区中文| 国产美女精品视频免费观看| 中文字幕在线日本| 久久字幕精品一区| 青草成人免费视频| www.国产一区二区| 亚洲欧美日韩在线观看a三区| 久久久久久久久久久网站| 欧美色图亚洲视频| 欧美阿v一级看视频| 欧美老少做受xxxx高潮| 无码人妻精品一区二区三区夜夜嗨| 天天天综合网| 久久久精品久久久| 午夜精品久久久久99蜜桃最新版| 精品国产a一区二区三区v免费| 亚洲美女久久久| 疯狂揉花蒂控制高潮h| 色愁久久久久久| 亚洲欧美激情四射在线日| 色婷婷在线影院| 欧美人与牛zoz0性行为| 亚洲天堂网在线观看| 五月婷婷欧美激情| 久久美女视频| 欧美成人午夜激情在线| 久草视频中文在线| 中文精品视频| 国产成人97精品免费看片| 久久久精品毛片| 捆绑调教美女网站视频一区| 亚洲a级在线播放观看| 99热这里只有精品在线观看| 国产成人综合亚洲网站| 国产精品夜夜夜一区二区三区尤| 午夜视频福利在线| 国产日韩在线不卡| 中文字幕黄色大片| av老司机在线观看| 在线免费观看日本欧美| 五月激情婷婷在线| 精品综合久久88少妇激情| 亚洲欧美自拍一区| 久久av红桃一区二区禁漫| 国产一区激情| 国产91亚洲精品| 国产老女人乱淫免费| 99久久99久久精品免费看蜜桃| 日本视频精品一区| 伊人精品影院| 日本乱人伦aⅴ精品| 亚洲图片 自拍偷拍| 欧美国产极品| 三级精品视频久久久久| 精品无码一区二区三区电影桃花| 久久不射网站| 亚洲自拍偷拍色图| 蜜桃视频在线观看视频| 亚洲另类色综合网站| 情侣黄网站免费看| 欧美经典一区| 亚洲色图25p| 久久中文字幕无码| 免费视频最近日韩| 久久久久久久久四区三区| 国产精品剧情| 色素色在线综合| 黑森林av导航| 婷婷综合视频| 国产精品久久久久77777| 性网爆门事件集合av| 中文字幕成人av| 国产极品在线视频| 香蕉成人app| 日韩一中文字幕| 男人日女人网站| 成人一道本在线| 日韩 欧美 自拍| 91亚洲视频| 亚洲国产欧美在线成人app| 午夜爽爽爽男女免费观看| 久久久久久自在自线| 北条麻妃高清一区| 黄色在线论坛| 欧美日韩三级在线| 精品人妻无码一区二区三区换脸| 一区二区三区网站| 国产日韩av高清| 风间由美一区| 色婷婷久久综合| 一级欧美一级日韩片| 激情欧美一区| 99在线国产| 亚洲夜夜综合| 欧美一三区三区四区免费在线看| 日本人亚洲人jjzzjjz| 久久国产日本精品| 欧美一区二区视频在线| 成人免费看黄| 亚洲免费高清视频| 国产成人精品777777| 91美女视频网站| 欧美a v在线播放| 日本韩国欧美超级黄在线观看| 久久久久久久久久国产精品| 欧美 中文字幕| 精品欧美一区二区三区| 久久国产精品无码一级毛片 | 免费黄色福利视频| 香蕉久久夜色精品国产更新时间 | 亚洲欧美国产精品专区久久| 美女又爽又黄免费视频| 久久亚洲一区二区三区四区| 男女午夜激情视频| 最新国产一区| 国产精品网站入口| 欧美激情黑人| 日韩一区二区免费视频| 久久精品这里只有精品| 国产91丝袜在线播放0| 蜜臀av无码一区二区三区| 久久亚洲黄色| 国产成人精品视频在线观看| 最新av网站在线观看 | 日韩中文字幕免费在线观看| 婷婷六月综合亚洲| 加勒比综合在线| 裸体在线国模精品偷拍| 欧美做受777cos| 巨人精品**| 国产精品视频资源| 伊人222成人综合网| 亚洲成人久久网| 国产成人无码专区| 亚洲三级在线观看| 亚洲啪av永久无码精品放毛片| 国产欧美激情| 亚洲午夜在线观看| av一级亚洲| 日韩av毛片网| 黄网站在线播放| 日韩大陆欧美高清视频区| av手机天堂网| 一区二区三区美女| 天堂久久精品忘忧草| 国产一区二区三区美女| 男人操女人逼免费视频| 成人激情免费视频| 国产精品麻豆免费版| 激情都市亚洲| 欧美国产高跟鞋裸体秀xxxhd| 三级视频在线| 日韩视频免费直播| 日本精品入口免费视频| 一二三区精品视频| 卡一卡二卡三在线观看| 成人免费高清在线观看| 亚欧美在线观看| 国产精品美女久久久| 国产四区在线观看| 加勒比久久综合| 国产精品jizz视频| 国产精品美女午夜爽爽| 68精品国产免费久久久久久婷婷| 无遮挡动作视频在线观看免费入口| 精品福利在线导航| 国产一区二区小视频| 色琪琪一区二区三区亚洲区| 麻豆亚洲av熟女国产一区二| 欧美国产丝袜视频| 久久久久成人精品无码中文字幕| 精品亚洲国内自在自线福利| 久久久久狠狠高潮亚洲精品| 国产精品chinese| 亚洲 国产 日韩 综合一区| 亚洲精品不卡在线观看| 国产精品自在线| 浪潮色综合久久天堂| 97在线观看免费高清| 日本乱理伦在线| 精品国偷自产在线| 爱爱爱免费视频在线观看| 亚洲精品成人av| av老司机久久| 91精品久久久久久久99蜜桃| 中文字幕av免费观看| 色狠狠一区二区三区香蕉| 亚欧视频在线观看| 亚洲国产一区视频| 免费在线视频观看| 亚洲精品日日夜夜| 玖玖爱这里只有精品| 中文字幕综合网| 色欲一区二区三区精品a片| 国产精品视频第一区| 久久亚洲无码视频| 国产亚洲综合av| 无码少妇精品一区二区免费动态| 91色在线porny| 久久久亚洲av波多野结衣| 91网址在线看| 国产乱了高清露脸对白| 99国产精品视频免费观看| 亚洲欧美日韩色| 99久久精品国产一区二区三区| 精品人妻一区二区免费| 成人动漫视频在线| 搡老熟女老女人一区二区| heyzo一本久久综合| 欧美成人三级伦在线观看| eeuss鲁片一区二区三区在线观看 eeuss影院一区二区三区 | 在线免费高清一区二区三区| 免费看欧美一级片| 亚洲一本视频| 日韩av三级在线| 久久中文欧美| 九一精品久久久| 国产v日产∨综合v精品视频| 国产精品亚洲一区二区无码| 99久久精品免费精品国产| 国产毛片久久久久久久| 中文字幕+乱码+中文字幕一区| 大吊一区二区三区| 自拍偷自拍亚洲精品播放| 九九热只有精品| 欧美三级免费观看| 中文字幕黄色av| 欧美一区2区视频在线观看| 刘亦菲毛片一区二区三区| 精品一区电影国产| www.国产精品.com| 欧美成人黑人xx视频免费观看| 成年人视频免费在线播放| 欧美亚州一区二区三区| 黄色成人小视频| 91成人免费看| 婷婷激情久久| 欧美爱爱视频网站| 尤物精品在线| 中国黄色片免费看| 成人午夜免费av| 中文字幕成人动漫| 亚洲精品国产第一综合99久久| 国产无套在线观看| 欧美视频一区二区三区在线观看| 99产精品成人啪免费网站| 亚洲经典中文字幕| 日韩伦理在线电影| 91精品国产99久久久久久| 久久久久黄色| 国产在线播放一区二区| 色综合久久网| 欧美黄色免费影院| 国产一区999| 性久久久久久久久久| 亚洲日本一区二区| 午夜影院免费在线观看| 日韩一区二区在线免费观看| 酒色婷婷桃色成人免费av网| 欧美日韩xxxxx| 欧美成人app| 精品蜜桃一区二区三区| 午夜欧美在线| 日韩有码免费视频| 成人免费电影视频| 国产福利视频网站| 色久综合一二码| 天天综合天天色| 精品中文字幕在线| 男女啪啪999亚洲精品| 激情伦成人综合小说| 亚洲午夜精品一区二区国产| 黄色国产小视频| 99精品视频在线观看| 免费看一级一片| 制服丝袜亚洲播放| 成av人电影在线观看| 97国产在线视频| 在线精品国产亚洲| 欧美一级免费在线观看| 日本在线不卡视频| 无码h肉动漫在线观看| 亚洲高清在线精品| www视频在线| 欧美大片va欧美在线播放| 91欧美精品| 亚洲 日韩 国产第一区| 天堂va蜜桃一区二区三区漫画版| 亚洲熟女一区二区| 亚洲激情六月丁香| 99久久精品日本一区二区免费| 最近2019中文字幕在线高清| 美女网站视频一区| 欧美日韩高清免费| 麻豆精品91| 少妇久久久久久久久久| 91久久香蕉国产日韩欧美9色| 日批视频在线播放| 97超碰色婷婷| 亚洲午夜久久| 国产a级片免费观看| 久久久噜噜噜久久人人看| 天堂а√在线中文在线新版| 日韩精品高清视频| 在线视频cao| 日本在线播放不卡| 日韩av电影免费观看高清完整版| 人人妻人人澡人人爽| 欧美在线小视频| 日本不卡视频| 亚洲精品免费在线视频| 午夜国产欧美理论在线播放 | 91美女蜜桃在线| 日韩在线播放中文字幕| 亚洲最大在线视频| 日本免费成人| 亚洲高潮无码久久| 国产91丝袜在线18| 日韩不卡在线播放| 一本一道久久a久久精品逆3p| jizz欧美| 日本在线视频www色| 成人毛片视频在线观看| 国产精品21p| 中文字幕精品www乱入免费视频| 欧美aaa级| 丁香婷婷综合激情| 91年精品国产| 亚洲图片欧美在线| 欧美巨乳在线观看| 欧美调教视频| 狠狠躁狠狠躁视频专区| 亚洲蜜桃精久久久久久久| 天天操天天操天天干| 国产精品电影网| 婷婷亚洲最大| 国产精品无码在线| 欧美日韩在线播| 婷婷色在线资源| 欧美一级二级三级| 国产自产高清不卡| 日韩三级av在线| 日韩一区二区三区xxxx| 欧美绝顶高潮抽搐喷水合集| 乌克兰美女av| 亚洲国产色一区| 波多野结衣在线影院| 国产福利久久| 欧美96一区二区免费视频| 福利一区二区三区四区| 在线视频精品一| 久久电影在线| 久久精品一二三四|