日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > Java > 正文

Java常用排序算法及性能測試集合

2019-11-26 16:04:34
字體:
來源:轉載
供稿:網友

現在再回過頭理解,結合自己的體會, 選用最佳的方式描述這些算法,以方便理解它們的工作原理和程序設計技巧。本文適合做java面試準備的材料閱讀。

先附上一個測試報告:

Array length: 20000
bubbleSort : 766 ms
bubbleSortAdvanced : 662 ms
bubbleSortAdvanced2 : 647 ms
selectSort : 252 ms
insertSort : 218 ms
insertSortAdvanced : 127 ms
insertSortAdvanced2 : 191 ms
binaryTreeSort : 3 ms
shellSort : 2 ms
shellSortAdvanced : 2 ms
shellSortAdvanced2 : 1 ms
mergeSort : 3 ms
quickSort : 1 ms
heapSort : 2 ms

通過測試,可以認為,冒泡排序完全有理由扔進垃圾桶。它存在的唯一理由可能是最好理解。希爾排序的高效性是我沒有想到的;堆排序比較難理解和編寫,要有宏觀的思維。

復制代碼 代碼如下:

package algorithm.sort;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * Java常用排序算法及性能測試集合
 *
 * 本程序集合涵蓋常用排序算法的編寫,并在注釋中配合極其簡單的特例講解了各種算法的工作原理,以方便理解和吸收;
 * 程序編寫過程中吸收了很多維基百科和別人blog上面的例子,并結合自己的思考,選擇并改進一個最容易讓人理解的寫法
 *(尤其是快速排序,我覺得我寫的算法最好理解)。
 * 同時包含一個集中式的性能測試和正確性測試方法,方便觀測。
 * @author /link.php?url=http://blog.csdn.net/sunxing007
 * 轉載請注明來自/link.php?url=http://blog.csdn.net/sunxing007
 */
public class SortUtil {
 // 被測試的方法集合
 static String[] methodNames = new String[]{
  "bubbleSort",
  "bubbleSortAdvanced",
  "bubbleSortAdvanced2",
  "selectSort",
  "insertSort",
  "insertSortAdvanced",
  "insertSortAdvanced2",
  "binaryTreeSort",
  "shellSort",
  "shellSortAdvanced",
  "shellSortAdvanced2",
  "mergeSort",
  "quickSort",
  "heapSort"
 };
    public static void main(String[] args) throws Exception{
     //correctnessTest();
     performanceTest(20000);
    }

    /**
     * 正確性測試<br>
     * 簡單地測試一下各個算法的正確性<br>
     * 只是為了方便觀測新添加的算法是否基本正確;<br>
     * @throws Exception 主要是反射相關的Exception;<br>
     */
    public static void correctnessTest() throws Exception{
     int len = 10;
     int[] a = new int[len];
     for(int i=0; i<methodNames.length; i++){
      for(int j=0; j<a.length; j++){
          a[j] = (int)Math.floor(Math.random()*len*2);
         }
      Method sortMethod = null;
      sortMethod = SortUtil.class.getDeclaredMethod(methodNames[i], a.getClass());
      Object o = sortMethod.invoke(null, a);
      System.out.print(methodNames[i] + " : ");
      if(o==null){
       System.out.println(Arrays.toString(a));
      }
      else{
       //兼顧mergeSort,它的排序結果以返回值的形式出現;
       System.out.println(Arrays.toString((int[])o));
      }
     }
    }

    /**
     * 性能測試<br>
     * 數組長度用參數len傳入,每個方法跑20遍取耗時平均值;<br>
     * @param len 數組長度 建議取10000以上,否則有些算法會顯示耗時為0;<br>
     * @throws Exception 主要是反射相關的Exception;<br>
     */
    public static void performanceTest(int len) throws Exception{
     int[] a = new int[len];
     int times = 20;

     System.out.println("Array length: " + a.length);
     for(int i=0; i<methodNames.length; i++){
      Method sortMethod = null;
      sortMethod = SortUtil.class.getDeclaredMethod(methodNames[i], a.getClass());
      int totalTime = 0;
      for(int j=0; j<times; j++){
       for(int k=0; k<len; k++){
           a[k] = (int)Math.floor(Math.random()*20000);
          }
       long start = new Date().getTime();
       sortMethod.invoke(null, a);
       long end = new Date().getTime();
       totalTime +=(end-start);
      }
      System.out.println(methodNames[i] + " : " + (totalTime/times) + " ms");
      //System.out.println(Arrays.toString(a));
     }
    }

    /**
     * 最原始的冒泡交換排序;<br>
     * 兩層遍歷,外層控制掃描的次數,內層控制比較的次數;<br>
     * 外層每掃描一次,就有一個最大的元素沉底;所以內層的比較次數將逐漸減小;<br>
     */
    public static void bubbleSort(int[] a){
        for(int i=0; i<a.length; i++){
            for(int j=0; j<a.length-i-1; j++){
                if(a[j]>a[j+1]){
                    int tmp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = tmp;
                }
            }
        }
    }

    /**
     * 改進的冒泡法<br>
     * 改進之處在于:設一個標志位,如果某趟跑下來,沒有發生交換,說明已經排好了;<br>
     */
    public static void bubbleSortAdvanced(int[] a){
        int k = a.length-1;
        boolean flag = true;
        while(flag){
            flag = false;
            for(int i=0;i<k;i++){
                if(a[i]>a[i+1]){
                    int tmp = a[i];
                    a[i] = a[i+1];
                    a[i+1] = tmp;
                    //有交換則繼續保持標志位;
                    flag = true;
                }
            }
            k--;
        }
    }

    /**
     * 改進的冒泡法2<br>
     * 改進之處在于吸收上面的思想(沒有交換意味著已經有序),如果局部的已經是有序的,則后續的比較就不需要再比較他們了。<br>
     * 比如:3142 5678,假如剛剛做完了2和4交換之后,發現這趟比較后續再也沒有發生交換,則后續的比較只需要比到4即可;<br>
     * 該算法就是用一個標志位記錄某趟最后發生比較的地點;<br>
     */
    public static void bubbleSortAdvanced2(int[] a){
        int flag = a.length - 1;
        int k;
        while(flag>0){
            k = flag;
            flag = 0;
            for(int i=0; i<k; i++){
                if(a[i] > a[i+1]){
                    int tmp = a[i];
                    a[i] = a[i+1];
                    a[i+1] = tmp;
                    //有交換則記錄該趟最后發生比較的地點;
                    flag = i+1;
                }
            }
        }
    }

    /**
     * 插入排序
     *
     * 關于插入排序,這里有幾個約定,從而可以快速理解算法:<br>
     * i: 無序表遍歷下標;i<n-1;<br>
     * j: 有序表遍歷下表;0<=j<i;<br>
     * a[i]:表示當前被拿出來做插入排序的無序表頭元素;<br>
     * a[j]:有序表中的任意元素;<br>
     * <br>
     * 算法關鍵點:把數組分割為a[0~i-1]有序表,a[i~n-1]無序表;每次從無序表頭部取一個,<br>
     * 把它插入到有序表適當的位置,直到無序表為空;<br>
     * 初始時,a[0]為有序表,a[1~n-1]為無序表;<br>
     */
    public static void insertSort(int[] a){
        //從無序表頭開始遍歷;
        for(int i=1; i<a.length; i++){
            int j;
            //拿a[i]和有序表元素依次比較,找到一個恰當的位置;
            for(j=i-1;j>=0; j--){
                if(a[j] < a[i]){
                    break;
                }
            }
            //如果找到恰當的位置,則從該位置開始,把元素朝后移動一格,為插入的元素騰出空間;
            if(j!=(i-1)){
                int tmp = a[i];
                int k;
                for(k = i-1; k>j;k--){
                    a[k+1] = a[k];
                }
                a[k+1] = tmp;
            }
        }
    }

    /**
     * 改進的插入排序1
     * 改進的關鍵在于:首先拿無序表頭元素a[i]和有序表尾a[i-1]比較,
     * 如果a[i]<a[i-1],說明需要調整;調整的過程為:
     * 從有序表尾開始,把有序表里面比a[i]大的元素都朝后移動,直到找到恰當的位置;
     */
    public static void insertSortAdvanced(int[] a){
        //遍歷無序表;
        for(int i=1; i<a.length; i++){
            //如果無序表頭元素小于有序表尾,說明需要調整;
            if(a[i]<a[i-1]){
                int tmp = a[i];
                int j;
                //從有序表尾朝前搜索并比較,并把大于a[i]的元素朝后移動以騰出空間;
                for(j=i-1; j>=0&&a[j]>tmp;j--){
                    a[j+1] = a[j];
                }
                a[j+1] = tmp;
            }
        }
    }

    /**
     * 改進的插入排序2
     * 總體思想和上面相似,拿無序表頭元素從有序表尾元素開始朝前比較,
     * 如果a[i]比a[i-1]小,則把a[i]從有序表尾用冒泡交換的方式朝前移動,直到到達恰當的位置;
     */
    public static void insertSortAdvanced2(int[] a){
        //遍歷無序表
        for(int i=1; i<a.length; i++){
            //拿a[i]從有序表尾開始冒泡;
            for(int j=i-1; j>=0 && a[j] > a[j+1]; j--){//a[j+1]就是a[i]
                int tmp = a[j];
                a[j] = a[j+1];
                a[j+1] = tmp;
            }
        }
    }

    /**
     * 快速排序<br>
     * 算法的思想在于分而治之:先找一個元素(一般來說都是數組頭元素),把比它大的都放到右邊,把比它小的都放到左邊;<br>
     * 然后再按照這樣的思想去處理兩個子數組; 下面說的子數組頭元素通指用來劃分數組的元素;<br>
     * <br>
     * 下面程序關鍵點就在于!forward, low0++, high0--這些運算; 這三個運算使得a[low0],a[high0]里面總有一個指向子數組頭元素; <br>  
     * 可以用極端的情況來方便理解這三個值的運作: <br>
     * 假如我的數列為0123456789, 初始時forward=false,0作為子數組劃分依據,很顯然第一輪的時候不會發生任何交換,low0一直指向0,<br>
     * high0逐漸下降直到它指向0為止; 同理可思考9876543210這個例子;<br>
     * <br>
     * @param a 待排序數組<br>
     * @param low 子數組開始的下標;<br>
     * @param high 子數組結束的下標;<br>
     */
    public static void quickSort(int[] a, int low, int high){
        if(low>=high){
            return;
        }
        int low0 = low;
        int high0 = high;
        boolean forward = false;
        while(low0!=high0){
            if(a[low0]>a[high0]){
                int tmp = a[low0];
                a[low0] = a[high0];
                a[high0] = tmp;
                forward = !forward;
            }
            if(forward){
                low0++;
            }
            else{
                high0--;
            }
        }
        low0--;
        high0++;
        quickSort(a, low, low0);
        quickSort(a, high0, high);
    }

    /**
     * 快速排序的簡單調用形式<br>
     * 方便測試和調用<br>
     * @param a
     */
    public static void quickSort(int[] a){
     quickSort(a, 0, a.length-1);
    }

    /**
     * 歸并排序<br>
     * 所謂歸并,就是合并兩個有序數組;歸并排序也用了分而治之的思想,把一個數組分為若干個子數組;<br>
     * 當子數組的長度為1的時候,則子數組是有序的,于是就可以兩兩歸并了;<br>
     * <br>
     * 由于歸并排序需要分配空間來轉儲歸并的結果,為了算法上的方便,歸并算法的結果以返回值的形式出現;<br>
     */

    /**
     * 合并兩個有序數組
     * @param a 有序數組1
     * @param b 有序數組2
     * @return 合并之后的有序數組;
     */
    public static int[] merge(int[] a, int[] b){
     int result[] = new int[a.length+b.length];
     int i=0,j=0,k=0;
     while(i<a.length&&j<b.length){
      if(a[i]<b[j]){
       result[k++] = a[i];
       i++;
      }
      else{
       result[k++] = b[j];
       j++;
      }
     }
     while(i<a.length){
      result[k++] = a[i++];
     }
     while(j<b.length){
      result[k++] = b[j++];
     }
     return result;
    }

    /**
     * 歸并排序<br>
     * 把數組從中間一分為二,并對左右兩部分遞歸調用,直到數組長度為1的時候,開始兩兩歸并;<br>
     * @param 待排序數組;
     * @return 有序數組;
     */
    public static int[] mergeSort(int[] a){
     if(a.length==1){
      return a;
     }
     int mid = a.length/2;
     int[] leftPart = new int[mid];
     int[] rightPart = new int[a.length-mid];
     System.arraycopy(a, 0, leftPart, 0, leftPart.length);
     System.arraycopy(a, mid, rightPart, 0, rightPart.length);
     leftPart = mergeSort(leftPart);
     rightPart = mergeSort(rightPart);
     return merge(leftPart, rightPart);
    }

    /**
     * 選擇排序<br>
     * 和插入排序類似,它也把數組分割為有序區和無序區,所不同的是:<br>
     * 插入排序是拿無序區的首元素插入到有序區適當的位置,而<br>
     * 選擇排序是從無序區中挑選最小的放到有序區最后;<br>
     * <br>
     * 兩層循環,外層控制有序區的隊尾,內層用來查找無序區最小元素;<br>
     * @param a
     */
    public static void selectSort(int[] a){
     for(int i=0; i<a.length; i++){
      int minIndex = i;
      for(int j=i+1; j<a.length; j++){
       if(a[j]<a[minIndex]){
        minIndex = j;
       }
      }
      int tmp = a[i];
      a[i] = a[minIndex];
      a[minIndex]= tmp;
     }
    }

    /**
     * 希爾排序<br>
     * 其思想是把數組按等步長(/間距)劃分為多個子序列,對各個子序列做普通的插入排序,<br>逐次降低步長,直到為1的時候最后再做一次普通的插入排序;
     * 用一個極端的例子作比方,我有數列如下:<br>
     * [1,2,3,4,5,6,7,8,9,10];<br>
     * 初始的時候,步長gap=5;則劃分的子數組為[1,6], [2,7], [3,8], [4,9], [5,10];<br>對他們分別排序(當然由于本數組特殊,所以結果是不變的);<br>
     * 然后gap=2=5/2; 子數組為[1,3,5,7,9], [2,4,6,8,10]; <br>
     * 最后gap=1=2/2; 做一次全局排序;<br>
     * <br>
     * 希爾排序克服了插入/冒泡排序的弱點(一次只能把元素移動一個相鄰的位置), <br>依靠大步長,可以把元素盡快移動到目標位置(或附近);<br>
     * 希爾排序實際上是插入排序的變種。它適用于:當數組總體有序,個別需要調整的情況;這時候利用插入排序的優勢,可以達到O(n)的效率;<br>
     * 影響希爾算法的一個重要的因素是步長選擇,一個好步長的優點是:后面的短步長排序不會破壞前面的長步長排序;<br>
     * 怎么理解這種破壞呢?前面的長步長把一個較小的數移到了左面,但是在縮小步長之后有可能又被交換到了右面 (因為它被分到了一個有很多比它更小的組);<br>
     * 關于步長,可以查看http://zh.wikipedia.org上面關于希爾排序的頁面;<br>
     * 下面的程序是希爾排序最基礎的寫法,適合用來理解希爾排序思想;<br>
     */
    public static void shellSort(int[] a){
     // 控制間距;間距逐漸減小,直到為1;
     for(int gap = a.length/2; gap>0; gap/=2){
      // 掃描每個子數組
      for(int i=0; i<gap; i++){
       // 對每個字數組,掃描無序區;注意增量;
       // a[i]是初始有序區;
       for(int j=i+gap; j<a.length; j+=gap){
        // 無序區首元素小于有序區尾元素,說明需要調整
        if(a[j]<a[j-gap]){
         int tmp = a[j];
         int k = j-gap;
         //從有序區尾向前搜索查找適當的位置;
         while(k>=0&&a[k]>tmp){
          a[k+gap] = a[k];
          k-=gap;
         }
         a[k+gap] = tmp;
        }
       }
      }
     }
    }

    /**
     * 改進的希爾排序<br>
     * 改進之處在于:上面的寫法用一個for循環來區別對待每個字數組;而實際上是不必要的;<br>
     * a[0,1,...gap-1]作為所有子數組的有序區,a[gap,...n-1]作為所有字數組的無序區;<br>
     * <br>
     * 該改進在時間效率上沒有改進;只是讓程序看起來更簡潔;<br>
     * @param a
     */
    public static void shellSortAdvanced(int[] a){
     // 控制步長
     for(int gap = a.length/2; gap>0; gap/=2){
      // 從無序區開始處理,把多個子數組放在一起處理;
      for(int j=gap; j<a.length; j++){
       // 下面的邏輯和上面是一樣的;
       if(a[j]<a[j-gap]){
        int tmp = a[j];
        int k = j-gap;
        while(k>=0&&a[k]>tmp){
         a[k+gap] = a[k];
         k-=gap;
        }
        a[k+gap] = tmp;
       }
      }
     }
    }

    /**
     * 改進的希爾排序2<br>
     * 在吸收shellSortAdvanced思想的基礎上,采用insertAdvanced2的做法;<br>即無序區首元素通過朝前冒泡的形式移動的適當的位置;<br>
     * @param a
     */
    public static void shellSortAdvanced2(int[] a){
     for(int gap = a.length/2; gap>0; gap/=2){
      for(int i=gap; i<a.length; i++){
       if(a[i]<a[i-gap]){
        for(int j=i-gap; j>=0&&a[j+gap]>a[j]; j-=gap){
         int tmp = a[j];
         a[j] = a[j+gap];
         a[j+gap] = tmp;
        }
       }
      }
     }
    }

    /**
     * 堆排序<br>
     * 堆的定義:堆是一個完全,或近似完全的二叉樹,堆頂元素的值大于左右孩子的值,左右孩子也需要滿足這個條件;<br>
     * 按照堆的定義,堆可以是大頂堆(maxHeap),或小頂堆(minHeap);<br>
     * 一般用數組即可模擬二叉樹,對于任意元素i,左孩子為2*i+1,右孩子為2*i+2;父節點為(i-1)/2;
     * @param a
     */
    public static void heapSort(int[] a){

     // 先從最后一個非葉子節點往上調整,使滿足堆結構;
     for(int i=(a.length-2)/2; i>=0; i--){
      maxHeapAdjust(a, i, a.length);
     }
     // 每次拿最后一個節點和第一個交換,然后調整堆;直到堆頂;
     for(int i=a.length-1; i>0; i--){
      int tmp = a[i]; a[i] = a[0]; a[0] = tmp;
      maxHeapAdjust(a, 0, i);
     }
    }

    /**
     * 調整堆<br>
     * 把以i為跟節點的二叉樹調整為堆;<br>
     * 可以這么來思考這個過程:這個完全二叉樹就像一個金字塔,塔頂的小元素沿著樹結構,往下沉降;<br>
     * 調整的結果是最大的元素在金字塔頂,然后把它從堆中刪除(把它交換到堆尾,然后堆收縮一格);<br>
     * 堆排序快的原因就是根據二叉樹的特點,一個節點要沉降到合適的位置,只需要logn步;同時前期調整的結果(大小順序)會被記錄下來,從而加快后續的調整;<br>
     * @param a 待排數組
     * @param i 堆頂
     * @param len 堆長度
     */
    public static void maxHeapAdjust(int[] a, int i, int len){
     int tmp = a[i];
     // j是左孩子節點
     int j = i*2+1;
     //
     while(j<len){
      // 從左右孩子中挑選大的
      // j+1是右孩子節點
      if((j+1)<len && a[j+1]>a[j]){
       j++;
      }
      // 找到恰當的位置就不再找
      if(a[j]<tmp){
       break;
      }
      // 否則把較大者沿著樹往上移動;
      a[i] = a[j];
      // i指向剛才的較大的孩子;
      i = j;
      // j指向新的左孩子節點;
      j = 2*i + 1;
     }
     // 把要調整的節點值下沉到適當的位置;
     a[i] = tmp;
    }

    /**
     * 二叉樹排序<br>
     * 二叉樹的定義是嵌套的:<br>節點的值大于左葉子節點的值,小于右葉子節點的值;葉子節點同樣滿足這個要求;<br>
     * 二叉樹的構造過程就是排序的過程:<br>
     * 先構造跟節點,然后調用add方法添加后續節點為跟節點的子孫節點;這個過程也是嵌套的;<br>
     * <br>
     * 中序遍歷二叉樹即得到有序結果;<br>
     * 二叉樹排序用法特殊,使用情形要視情況而定;<br>
     * @param a
     */
    public static void binaryTreeSort(int[] a){
     // 構造一個二叉樹節點內部類來實現二叉樹排序算法;
     class BinaryNode{
      int value;
      BinaryNode left;
      BinaryNode right;

      public BinaryNode(int value){
       this.value = value;
       this.left = null;
       this.right = null;
      }

      public void add(int value){
       if(value>this.value){
        if(this.right!=null){
         this.right.add(value);
        }
        else{
         this.right = new BinaryNode(value);
        }
       }
       else{
        if(this.left!=null){
         this.left.add(value);
        }
        else{
         this.left = new BinaryNode(value);
        }
       }
      }
      /**
       * 按中序遍歷二叉樹,就是有序的。
       */
      public void iterate(){
       if(this.left!=null){
        this.left.iterate();
       }
       // 在測試的時候要把輸出關掉,以免影響性能;
       // System.out.print(value + ", ");
       if(this.right!=null){
        this.right.iterate();
       }
      }
     }

     BinaryNode root = new BinaryNode(a[0]);
     for(int i=1; i<a.length; i++){
      root.add(a[i]);
     }
     root.iterate();
    }
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
欧美日韩中文字幕精品| 国产主播中文字幕| 国产一卡2卡3卡免费网站 | 国产羞羞视频在线播放| 国产在线观看精品| 亚洲成在线观看| 国产中文伊人| 国产一级在线播放| 欧美日韩亚洲综合| 欧美另类久久久品| 欧洲精品二区| 日韩在线不卡| 亚洲一级影院| 亚洲第一精品在线| av中文网站| 亚洲福利在线观看| 最新日韩中文字幕| 国产黄色一区| √新版天堂资源在线资源| 日韩免费精品视频| 天天摸日日摸狠狠添| 国产三级免费观看| 最新中文在线视频| 国内激情久久| 国产一级在线| 一区二区中文字幕在线| 日韩精品大片| 日韩欧美综合视频| 99久久www免费| 欧美xxxx中国| 午夜视频在线观看一区| 视频一区二区精品的福利| 日韩视频一区| 国产福利一区二区| 精品在线一区二区| 国产超级va在线视频| 欧美日韩性视频一区二区三区| 国产黄色高清在线| 亚洲欧美99| 国产aa精品| 欧美日韩国产高清| 国产欧美日韩最新| 久久麻豆视频| 国产成人综合精品| 精品国产乱码一区二区| 91精品国产99| 精品人妻一区二区三区视频| 国产日韩精品在线| 在线视频观看日韩| av三级在线观看| 日韩福利视频导航| 日韩精品视频免费| 中文字幕日韩欧美在线视频| 中文字幕在线观看国产| 欧美日韩国产一二| 欧美日韩精品区| 影音先锋中文字幕在线观看| 中文字幕日韩高清| 亚洲免费观看在线观看| 国产黄色网页| 精品视频久久| 国产婷婷色一区二区三区| 亚洲福利精品在线| 欧美日韩免费不卡视频一区二区三区| 亚洲国产综合久久| 欧美熟妇乱码在线一区| 久久久精品国产99久久精品芒果| 精品国产乱码一区二区| 亚洲视频资源在线| 99国产一区| 国产小视频免费在线观看| 一区二区三区在线不卡| 在线观看av的网站| 欧美三级日韩三级| 免费在线播放av| 中文亚洲欧美| 91精品综合久久久久久| 欧美日韩久久久| 欧美日韩中文字幕在线观看| 国产福利精品导航| 日韩中文字幕国产| 不卡专区在线| 91精品视频免费在线观看| 欧美日韩综合视频网址| 精品午夜av| 欧美日韩高清一区二区不卡| 亚洲羞羞网站| 日韩三级视频在线播放| 欧美日韩久久久| 欧美va亚洲va日韩∨a综合色| 亚洲欧美日本另类| 欧美一级免费看| 国产不卡精品在线| 国产成人中文字幕| 先锋男人资源站| 69免费视频| 免费在线视频一级不卡| a天堂在线资源| 日韩高清不卡一区| 国产区日韩欧美| √新版天堂资源在线资源| 亚洲精品中文字幕乱码三区| 中文字幕精品一区二区三区在线| 亚洲热线99精品视频| 欧美国产日韩在线播放| 亚洲一区中文字幕在线| 精品乱人伦一区二区三区| 精人妻一区二区三区| 日韩精品视频在线播放| 欧美wwww| 黄色片网站在线| 国产日韩亚洲欧美| 中文字幕亚洲国产| 国产区高清在线| 亚洲一区日韩在线| 日韩三级精品电影久久久| 国产1区在线| 久久精品99国产国产精| 国产色综合网| 国产午夜精品视频免费不卡69堂 | 国产 欧美 在线| 老司机久久99久久精品播放免费| 亚洲羞羞网站| 欧美日韩中文字幕在线| 日韩精品不卡一区二区| 99视频一区| 91精品国产综合久久久久久| 日韩精品中文字幕第1页| 91精品国产综合久久久蜜臀粉嫩| 国产一二三视频| 欧美变态tickling挠脚心| 国产91欧美| 国产乱国产乱老熟300| 欧美激情一区二区在线| 中文字幕欧美在线| 91精品久久久久| 日韩欧美亚洲日产国| 国产视频1区2区| 亚洲图片小说综合| 精品中文在线| 精品日韩在线播放| 精品亚洲永久免费| 亚洲深夜福利| 欧美日韩久久久| 91蜜桃在线视频| 中文字幕在线日韩| 国产欧美日韩高清| 日韩欧美国产1| 亚洲一区视频在线观看视频| 中文字幕精品一区二| 日韩精品视频在线| 国产在线导航| 久久欧美中文字幕| 国产无遮挡在线视频免费观看| 欧美日韩精品不卡| 中文字幕欧美日韩va免费视频| 日本不卡视频一区| 欧美日韩精品综合在线 | 深夜福利一区| 欧美日韩性视频在线| 欧美不卡视频| 黄色国产网站在线观看| 欧美日韩夫妻久久| 日韩精品一级| 欧美 日韩 国产在线| 国产又粗又猛又爽又黄91精品| 二区三区中文字幕| 99久久婷婷| 亚洲免费中文字幕| 欧美日韩国产免费观看视频| 国产乱码午夜在线视频| 欧美久久久网站| 久久久精品午夜少妇| 亚洲天堂国产视频| 国产午夜在线观看| 国产成免费视频| 午夜亚洲一区| www.老鸭窝.com| 欧美一级欧美三级在线观看| 国产字幕在线看| 一本大道一区二区三区| 国产最顶级的黄色片在线免费观看| 欧美日韩国产专区| 午夜精品一区二区三区免费视频| 国产日韩成人精品| 91精品在线观看视频| 91精品视频国产| 在线中文字幕网站| 国产午夜在线观看| 一区免费在线| 精品国产999| 国产日韩第一页v| 精品国内自产拍在线视频| 中文字幕日韩亚洲| 一本一道久久a久久精品综合蜜臀| 中文字幕在线日韩| 日韩视频 中文字幕| 黄色在线播放网站| 日韩中文欧美在线| 欧美日韩尤物久久| 欧美日韩国产影片| 午夜一区二区视频| 国产一二三视频| 精品久久人人做人人爽| 欧美日韩国产免费| 一区二区国产在线| 日韩欧美国产成人精品免费| 视频一区中文字幕国产| 亚洲中文字幕一区| 99视频精品全国免费| 欧美日韩免费高清| 在线一区av| 91精品国产综合久久精品app| 日韩在线视频观看| 极品久久久久久| 日韩精品视频在线免费观看| 中文网丁香综合网| 久久久久久久久99精品| 日本中文字幕在线观看| 91精品国产综合久久香蕉最新版 | 久久99久久99精品中文字幕| 91精品日本| 日本国产在线视频| 91精品久久久久久蜜臀| 欧美日韩中文| 亚洲深夜福利| 亚洲欧洲一区二区天堂久久| 高清国产一区| 97天天综合网| 国产精品福利视频一区二区三区| 成人精品国产福利| 国产偷国产偷亚洲清高网站 | 三级网站免费观看| 日韩视频一区| 一区二区国产在线| 中文精品在线| 中文字幕视频在线免费欧美日韩综合在线看| 日本a级黄色| 日韩视频精品在线| 大香一本蕉伊线亚洲网| www中文字幕| 日韩欧美综合| 国产乱国产乱300精品| 中文字幕日韩在线视频| 日韩中文字幕国产| 久久香蕉一区| a√免费观看在线网址www| 亚洲第一视频| 91精品国产欧美日韩| 欧美日韩成人一区二区| 国产欧美日韩中文| 99久久www免费| 中文字幕在线亚洲| 中文字幕在线国产| 日韩在线视频一区二区三区| 日韩欧美国产网站| 国产一二三区精品视频| 99国产成 人 综合 亚洲欧美 | 一区二区欧美国产| 麻豆一区二区99久久久久| 国产v日产∨综合v精品视频| 国产拍揄自揄精品视频麻豆| 久久精品99久久久久久久久| 亚洲专区一区| 日韩中文字幕网| 精品国产免费视频| 欧美,日韩,国产在线| 日韩色在线观看| 久久99精品久久久久久青青日本| 欧洲精品二区| 91精品国产色综合久久久蜜香臀| 欧美日韩国产高清| 国产欧美日韩视频| 精品播放一区二区| 日本不卡高清视频一区| 日韩不卡一区二区| 国产最新在线| 中文av字幕一区| 日韩久久久精品| 国产视频三级在线观看播放| 精品视频999| 日韩欧美不卡视频| 欧美日韩国产中字| 在线观看国产福利视频| 日韩一级免费在线观看| 国产日韩三级| 91www成人久久| 欧美日韩在线视频免费观看| 国产欧美日韩视频| 欧美日韩精品久久久| 日韩精品资源二区在线| 快she精品国产999| 国产高清一区| 欧美亚洲国产日韩| 亚欧成人精品| 国产在线精品国自产拍免费| 欧美日韩午夜在线视频| 一区二区三区精品久久久| 亚洲欧洲日韩在线| 欧美日韩中文字幕在线| 欧美日韩亚洲天堂| 欧美日韩精品免费在线观看视频| 午夜一区二区三区视频 | 在线观看一区日韩| 国产日韩三级| 在线不卡一区二区| 国产字幕中文| 国内精品99| 日韩欧美在线第一页| 在线精品视频免费播放| 国产在线拍偷自揄拍精品| 中文字幕精品视频在线| 第一页在线观看| 精品熟女一区二区三区| 免费视频二区| 免费视频久久| 91精品在线观看视频| 欧美熟妇乱码在线一区| 91亚洲欧美| 国产成人精品免费在线| 亚洲三级网站| 一区二区视频国产| 日韩国产专区| 欧美三级在线视频| 午夜国产视频 | 国内不卡的二区三区中文字幕| 91精品国产综合久久香蕉最新版| 欧美在线视频第一页| 在线观看av的网站| 欧美日韩国产区| √新版天堂资源在线资源| 欧美成人二区| 亚洲高清视频一区| 日韩欧美一二三| 日韩久久在线| 在线视频你懂得一区| 中文字幕在线观看欧美| 最近中文字幕日韩精品| 国产区视频在线观看| 国产999在线观看| 国产免费久久| 久久久久蜜桃| 99精品一级欧美片免费播放| 中文字幕欧美日韩| 久精品在线观看| 一级日韩一级欧美| 成人禁用看黄a在线| 欧美日中文字幕| 91精品国产自产在线| 中文字幕日韩免费视频| 视频一区二区精品的福利| 欧美日韩免费高清| 视频一区不卡| 欧美日韩久久久| 在线视频国内一区二区| 日本亚洲视频在线| 亚洲福利精品| 精品国产免费观看一区| 国产一级粉嫩xxxx| 日韩不卡高清视频| 亚洲三级中文字幕| www中文字幕| 99色在线视频| 日韩久久久精品| 国产欧美综合在线| 欧美一级日韩不卡播放免费| 日韩在线视频在线观看| 日韩高清在线一区二区| 亚洲视频一二三四| 欧美.日韩.国产.一区.二区| 欧美片网站免费| 在线日韩中文字幕| 日韩中文字幕亚洲| 成年人看的羞羞网站| 日韩精品乱码av一区二区| 日韩精品在线免费观看| 一区二区三区在线免费| 日韩视频第二页| 中文字幕在线视频网| 日韩av一区二区在线| 欧美日韩精品区| 国产色综合网| 91精品视频观看| 国产免费一级片| 亚洲成av人片在线| 国产导航在线| 中文字幕亚洲一区在线观看| 国产视频aaa| 精品网站999| 欧美亚洲天堂| 亚洲综合在线中文字幕| 在线一区免费| 亚洲国产午夜精品| 91精品蜜臀在线一区尤物| 99热最新网址| 日韩精品在线免费看| 欧美三级免费观看| 精品视频国产| 精品国产99久久久久久| 日韩不卡在线观看|