日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

一文了解树在前端中的应用,掌握数据结构中树的生命线

發布時間:2023/12/4 HTML 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文了解树在前端中的应用,掌握数据结构中树的生命线 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一文了解樹在前端中的應用

  • 🏕?序言
  • 🌲一、樹是什么?
  • 🌴二、深/廣度優先遍歷
    • 1、深度優先遍歷
      • (1)定義
      • (2)口訣
      • (3)代碼實現
    • 2、廣度優先遍歷
      • (1)定義
      • (2)口訣
      • (3)代碼實現
  • 🌱三、二叉樹
    • 1、定義
    • 2、二叉樹的先/中/后序遍歷
      • (1)先序遍歷
      • (2)中序遍歷
      • (3)后序遍歷
    • 3、JS實現先中后序三種遍歷
      • (1)JS實現二叉樹的先序遍歷
      • (2)JS實現二叉樹的中序遍歷
      • (3)JS實現二叉樹的后序遍歷
      • (4)總結
  • ??四、leetcode經典題目剖析
    • 1、leetcode104二叉樹的最大深度(簡單)
    • 2、leetcode111二叉樹的最小深度(簡單)
    • 3、leetcode102二叉樹的層序遍歷(中等)
    • 4、leetcode94二叉樹的中序遍歷(簡單)
    • 5、leetcode112路徑總和(簡單)
    • 6、leetcode129求根節點到葉節點數字之和(中等)
  • 🎄五、前端與樹:遍歷JSON的所有節點值
    • 1、碎碎念
    • 2、代碼實現
      • (1)制造數據
      • (2)遍歷節點值
      • (3)打印結果
  • 🏡六、結束語
  • 🐣彩蛋One More Thing
    • (:往期推薦
    • (:番外篇

🏕?序言

在我們的日常生活中,無時無刻都會看到樹。比如,在街上行走時,就有著一排排的樹。那么,樹在前端中,都有哪些應用呢?

事實上,前端在寫頁面時,每個頁面就有它對應的 DOM 樹、 CSSOM 樹等等。除此之外呢,像我們寫級聯選擇器時,它也是一層疊一層的,就像一棵樹一樣。

在接下來的這篇文章中,將講解樹這個數據結構的一些基本操作,以及樹在前端中的應用。

一起來學習叭~🧐

🌲一、樹是什么?

  • 樹是一種具有分層數據功能的抽象模型。
  • 前端工作中常用的樹包括: DOM 樹、級聯選擇、樹形空間……。
  • JS 中沒有樹,但是可以用 Object 和 Array 構建樹。
  • 樹的常用操作:深度/廣度優先遍歷、先中后序遍歷。

🌴二、深/廣度優先遍歷

1、深度優先遍歷

(1)定義

  • 深度優先遍歷,即盡可能深的搜索樹的分支。

(2)口訣

  • 訪問根節點。
  • 對根節點的 children 挨個進行深度優先遍歷。

(3)代碼實現

接下來用 JS 來實現樹的深度優先遍歷。具體代碼如下:

const tree = {val:'a',children:[{val:'b',children:[{val:'d',children:[]},{val:'e',children:[]}]},{val:'c',children:[{val:'f',children:[]},{val:'a',children:[]}]}] }const dfs = (root) => {console.log(root.val);// 使用遞歸root.children.forEach(dfs); }/* 打印結果: a b d e c f a */

通過以上代碼我們可以知道,首先我們先定義一棵樹 tree ,之后使用遞歸的方法,對樹的 Children 挨個進行遍歷,最終得到 abdecfa 的打印結果。

這個順序怎么理解會更為容易一點呢?

在上面的知識點我們談到,樹是往深了遍歷。那在我們這道題的 tree 樹當中,我們總得先對第一層的遍歷完,才能遍歷第二層的。而第一層的內容又有很多層,那就先把它往深了遍歷,等到第一層的深度遍歷結束后,我們才開始遍歷第二層的。

所以,我們先在來看一下,最上面的是 a ,接著就是第一層,第一層有 bde ,接下來是第二層,第二層就有 cfa 。因此,最終的順序為 abdecfa 。

2、廣度優先遍歷

(1)定義

  • 廣度優先遍歷,即先訪問根節點最近的節點

(2)口訣

  • 新建一個隊列。
  • 把隊頭出隊并訪問。
  • 把隊頭的 children 挨個入隊。
  • 重復第二步和第三步,直到隊列為空。

(3)代碼實現

接下來用 JS 來實現樹的廣度優先遍歷。具體代碼如下:

const tree = {val:'a',children:[{val:'b',children:[{val:'d',children:[]},{val:'e',children:[]}]},{val:'c',children:[{val:'f',children:[]},{val:'a',children:[]}]}] }const bfs = (root) => {// 新建一個隊列,并把根節點先放到隊列里面const q = [root];while(q.length > 0){// 不斷進行出隊,訪問const n = q.shift();// 邊出隊邊訪問console.log(n.val);// 把隊頭的children挨個入隊,退到隊列里面n.children.forEach(child => {q.push(child);});} }bfs(tree);/* 打印結果: a b c d e f a */

🌱三、二叉樹

1、定義

  • 對于二叉樹來說,樹中的每個節點最多只能有兩個子節點
  • JS 中沒有二叉樹,但通常用對象 Object 模擬二叉樹。

2、二叉樹的先/中/后序遍歷

(1)先序遍歷

  • 訪問根節點。
  • 對根節點的左子樹進行先序遍歷。
  • 對根節點的右子樹進行先序遍歷。

(2)中序遍歷

  • 對根節點的左子樹進行中序遍歷。
  • 訪問根節點。
  • 對根節點的右子樹進行中序遍歷。

(3)后序遍歷

  • 對根節點的左子樹進行后序遍歷。

  • 對根節點的右子樹進行后序遍歷。

  • 訪問根節點。

3、JS實現先中后序三種遍歷

下面我們用代碼來實現二叉樹的這三種遍歷。接下來開始講解~

(1)JS實現二叉樹的先序遍歷

對于二叉樹的先序遍歷來說,是先訪問根節點,之后再訪問左子樹,最后訪問右子樹。下面我們用兩種方式來實現先序遍歷,第一種是遞歸版本,第二種是非遞歸版本

先定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實現:

// 遞歸版本實現 const preOrder1 = (root) => {if(!root){return;}console.log(root.val);preOrder1(root.left);preOrder1(root.right); }preOrder1(bt); /**打印結果: 1 2 4 5 3 6 7 */

非遞歸版本實現:

// 非遞歸版實現 /*** 思路:* 1.新建一個棧模擬函數的調用堆棧;* 2.對于先序遍歷來說,需要先把根節點取出,然后再遍歷左子樹了右子樹;* 3.按照棧的先進后出特點,先把右子樹放進棧里,再把左子樹放進棧里,一一取出。*/ const preOrder2 = (root) => {if(!root){return;}// 新建一個stack代表函數的調用堆棧const stack = [root];// console.log(stack)while(stack.length){// 將根節點從棧里彈出const n = stack.pop();console.log(n.val);if(n.right){stack.push(n.right);}if(n.left){stack.push(n.left);}} }preOrder2(bt); /**打印結果: 1 2 4 5 3 6 7 */

(2)JS實現二叉樹的中序遍歷

對于二叉樹的中序遍歷來說,是先訪問子樹,之后訪問節點,最后再訪問子樹。下面我們用兩種方式來實現中序遍歷,第一種是遞歸版本,第二種是非遞歸版本

同樣地,我們先來先定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實現:

// 遞歸版本實現 const inOrder1 = (root) => {if(!root){return;}inOrder(root.left);console.log(root.val);inOrder(root.right); }inOrder1(bt); /**打印結果: 4 2 5 1 6 3 7 */

非遞歸版本實現:

// 非遞歸版實現 /*** 思路:* 1.新建一個棧模擬函數的調用堆棧;* 2.對于中序遍歷來說,需要先把左子樹全部丟到棧里面;那么需要每當遍歷一個,就推到棧里面* 3.遍歷完成之后,把最盡頭的結點彈出,并訪問它;此處最盡頭的結點即盡頭出的根節點,左根右* 4.訪問完左結點后,需要訪問右結點;*/ const inOrder2 = (root) => {if(!root){return;}let p = root;const stack = [];while(p || stack.length){while(p){// 先進棧stack.push(p);// 進棧完繼續指向左子樹p = p.left;}// 彈出最后一個const n = stack.pop();console.log(n.val);p = n.right;}}inOrder2(bt); /**打印結果: 4 2 5 1 6 3 7 */

(3)JS實現二叉樹的后序遍歷

對于二叉樹的后序遍歷來說,是先訪問子樹,之后訪問子樹,最后再訪問節點。下面我們用兩種方式來實現后序遍歷,第一種是遞歸版本,第二種是非遞歸版本

首先同樣地,先來定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實現:

// 遞歸版本實現 const postOrder1 = (root) => {if(!root){return;}postOrder1(root.left);postOrder1(root.right);console.log(root.val); }preOrder1(bt); /**打印結果: 1 2 4 5 3 6 7 */

非遞歸版本實現:

// 非遞歸版實現 /*** 思路:* 1.建立一個空棧stack;* 2.分別把左子樹,右子樹分別放入stack棧* 3.建立一個倒序棧outputStack,先把根樹放進,再一一放入右子樹,右子樹全部放完之后再放左子樹*/ const postOrder2 = (root) => {if(!root){return;}// 倒序棧輸出,放根右左的順序,之后再一一取出const outputStack = [];// 先放左子樹,再放右子樹,方便后面取出const stack = [root];while(stack.length){const n = stack.pop();outputStack.push(n);if(n.left){stack.push(n.left);}if(n.right){stack.push(n.right);}}while(outputStack.length){const n = outputStack.pop();console.log(n.val);} } preOrder2(bt); /**打印結果: 1 2 4 5 3 6 7 */

(4)總結

看完上面的代碼實現后,我們來做個總結。為什么這里要展示遞歸版本和非遞歸版本呢?

事實上,在我們的日常開發中,遞歸遍歷是非常常見的。但試想一下,有時候我們的業務邏輯有可能很復雜,那這個時候前端從后端接收到的數據量是比較大的。這個時候如果用遞歸版本來處理的話,算法復雜度相對來說就會比較高了。

所以我們多了一種非遞歸版本的實現方式,非遞歸版本的實現方式,旨在以空間來換時間,減少代碼的時間復雜度。

??四、leetcode經典題目剖析

接下來我們引用幾道經典的 leetcode 算法,來鞏固樹和二叉樹的知識。

1、leetcode104二叉樹的最大深度(簡單)

(1)題意

附上題目鏈接:leetcode104二叉樹的最大深度

給定一個二叉樹,找出其最大深度。

二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

輸入輸出示例:

  • 輸入: 給定二叉樹 [3,9,20,null,null,15,7]
  • 輸出: 3

(2)解題思路

  • 求最大深度,考慮使用深度優先遍歷
  • 在深度優先遍歷過程中,記錄每個節點所在的層級,找出最大的層級即可。

(3)解題步驟

  • 新建一個變量,記錄最大深度。
  • 深度優先遍歷整棵樹,并記錄每個節點的層級,同時不斷刷新最大深度的這個變量。
  • 遍歷結束返回最大深度的變量。

(4)代碼實現

/*** @param {TreeNode} root* @return {number}*/ let maxDepth = function(root) {let res = 0;const dfs = (n, l) => {if(!n){return;}if(!n.left && !n.right){res = Math.max(res, l);}dfs(n.left, l + 1);dfs(n.right, l + 1);}dfs(root, 1);return res; }

2、leetcode111二叉樹的最小深度(簡單)

(1)題意

附上題目鏈接:leetcode111二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

**說明:**葉子節點是指沒有子節點的節點。

輸入輸出示例:

  • 輸入: root = [3,9,20,null,null,15,7]
  • 輸出: 2

(2)解題思路

  • 求最小深度,考慮使用廣度優先遍歷。
  • 在廣度優先遍歷過程中,遇到葉子節點,停止遍歷,返回節點層級。

(3)解題步驟

  • 廣度優先遍歷整棵樹,并記錄每個節點的層級。
  • 遇到葉子節點,返回節點層級,停止遍歷。

(4)代碼實現

/*** @param {TreeNode} root* @return {number}*/let minDepth = function(root){if(!root){return 0;}const q = [[root, 1]];while(q.length){const [n, l] = q.shift();if(!n.left && !n.right){return l;}if(n.left){q.push([n.left, l + 1]);}if(n.right){q.push([n.right, l + 1]);}} }

3、leetcode102二叉樹的層序遍歷(中等)

(1)題意

附上題目鏈接:leetcode102二叉樹的層序遍歷

給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。

輸入輸出示例:

  • 輸入: 二叉樹:[3,9,20,null,null,15,7]

    3/ \9 20/ \15 7
  • 輸出:

    [[3],[9,20],[15,7] ]

(2)解題思路

  • 層序遍歷順序就是廣度優先遍歷。
  • 不過在遍歷時候需要記錄當前節點所處的層級,方便將其添加到不同的數組中。

(3)解題步驟

  • 廣度優先遍歷二叉樹。
  • 遍歷過程中,記錄每個節點的層級,并將其添加到不同的數組中。

(4)代碼實現

/*** @param {TreeNode} root* @return {number[][]}*/ // 方法一 let levelOrder1 = function(root) {if(!root){return [];}const q = [[root, 0]];const res = [];while(q.length){const [n, level] = q.shift();if(!res[level]){// 沒有該層次的數組時先創建一個數組res.push([n.val]);}else{// 有數組時直接將值放進res[level].push(n.val);}if(n.left){q.push([n.left, level + 1]);}if(n.right){q.push([n.right, level + 1]);}}return res; };// 方法二 let levelOrder2 = function(root){if(!root){return [];}const q = [root];const res = [];while(q.length){let len = q.length;res.push([]);while(len--){const n = q.shift();res[res.length - 1].push(n.val);if(n.left){q.push(n.left);}if(n.right){q.push(n.right);}}}return res; }

4、leetcode94二叉樹的中序遍歷(簡單)

(1)題意

附上題目鏈接:leetcode94二叉樹的中序遍歷

給定一個二叉樹的根節點 root ,返回它的 中序 遍歷。

輸入輸出示例:

  • 輸入: root = [1,null,2,3]
  • 輸出: [1,3,2]

(2)解題思路&&解題步驟

  • 這里的解題思路和步驟和上方講中序遍歷時類似,所以不再做講解,下面直接看代碼實現。

(3)代碼實現

/*** @param {TreeNode} root* @return {number[]}*/ // 遍歷版本let inorderTraversal1 = function(root) {const res = [];const rec = (n) => {if(!n){return;}rec(n.left);rec(n.val);rec(n.right);}rec(root);return res; };// 迭代版本——棧方法 let inorderTraversal2 = function(root){const res = [];const stack = [];let p = root;while(stack.length || p){while(p){stack.push(p);p = p.left;}const n = stack.pop();res.push(n.val);p = n.right;}return res; }inorderTraversal1(root); inorderTraversal2(root);

5、leetcode112路徑總和(簡單)

(1)題意

附上題目鏈接:leetcode112路徑總和

給你二叉樹的根節點 root 和一個表示目標和的整數 targetSum ,判斷該樹中是否存在 根節點到葉子節點 的路徑,這條路徑上所有節點值相加等于目標和 targetSum 。

葉子節點 是指沒有子節點的節點。

輸入輸出示例:

  • 輸入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
  • 輸出: true

(2)解題思路

  • 在深度優先遍歷的過程中,記錄當前路徑思維節點值的和。
  • 在葉子節點處,判斷當前路徑的節點值的和是否等于目標值。

(3)解題步驟

  • 深度優先遍歷二叉樹,在葉子節點處,判斷當前路徑路徑的節點值的和是否等于目標值,是就返回true。
  • 遍歷結束,如果沒有匹配,就返回false。

(4)代碼實現

/*** @param {TreeNode} root* @param {number} targetSum* @return {boolean}*/ // 遞歸法 let hasPathSum = function(root, targetSum) {if(!root){return false;}let res = false;const dfs = (n, s) => {if(!n.left && !n.right && s === targetSum){res = true;}if(n.left){dfs(n.left, s + n.left.val);}if(n.right){dfs(n.right, s + n.right.val);}}dfs(root, root.val);return res; };

6、leetcode129求根節點到葉節點數字之和(中等)

(1)題意

附上題目鏈接:leetcode129求根節點到葉節點數字之和

給你一個二叉樹的根節點 root ,樹中每個節點都存放有一個 0 到 9 之間的數字。

每條從根節點到葉節點的路徑都代表一個數字:

例如,從根節點到葉節點的路徑 1 -> 2 -> 3 表示數字 123 。

計算從根節點到葉節點生成的 所有數字之和

葉節點 是指沒有子節點的節點。

輸入輸出示例:

  • 輸入: root = [1,2,3]
  • 輸出: 25
  • 解釋:
    • 從根到葉子節點路徑 1->2 代表數字 12
    • 從根到葉子節點路徑 1->3 代表數字 13
    • 因此,數字總和 = 12 + 13 = 25

(2)解題思路

  • 在深度優先遍歷的過程中,記錄當前路徑前面節點的值。
  • 在葉子節點處,計算出當前路徑值。

(3)解題步驟

  • 深度優先遍歷二叉樹,直到每一棵樹的葉子節點處結束。
  • 遍歷結束,返回所有路徑值。

(4)代碼實現

/*** @param {TreeNode} root* @return {number}*/var sumNumbers = function(root) {// 深度優先遍歷處理const dfs = (n, preNum) => {if(!n){return 0;}const sum = preNum * 10 + n.val;if(!n.left && !n.right){return sum;}else{return dfs(n.left, sum) + dfs(n.right, sum);}}return dfs(root, 0); };

🎄五、前端與樹:遍歷JSON的所有節點值

1、碎碎念

有時候,后端傳過來的數據可能不是很友好,有可能一串數據里面又是對象又是數組的,這個時候前端拿到數據后,就需要稍微處理一下了。

因此,我們可以通過深度優先遍歷來遍歷 JSON 中的所有節點值。

接下來用一個例子來展示~

2、代碼實現

(1)制造數據

假設我們心在有一串 json 的數據,代碼如下:

const json = {a:{b:{c:1}},d:[1, 2] }

(2)遍歷節點值

接下來,我們用深度優先遍歷的方式,來遍歷 JSON 中的所有節點值。具體實現代碼如下:

const dfs = (n, path) => {console.log(n, path);Object.keys(n).forEach(k => {dfs(n[k], path.concat(k));}); };dfs(json, []);

(3)打印結果

最終打印結果如下:

{ a: { b: { c: 1 } }, d: [ 1, 2 ] } [] { b: { c: 1 } } [ 'a' ] { c: 1 } [ 'a', 'b' ] 1 [ 'a', 'b', 'c' ] [ 1, 2 ] [ 'd' ] 1 [ 'd', '0' ] 2 [ 'd', '1' ]

大家看上面的打印結果可以發現,通過深度優先遍歷的方式,數據都被一一遍歷出來。因此,對于樹這種數據結構來說,在前端當中出現的頻率也是較高的~~

🏡六、結束語

通過上文的學習,我們了解了樹的兩種遍歷:深度優先遍歷和廣度優先遍歷。同時,還有一種特殊的樹,二叉樹。二叉樹在面試中,基本上是一大必考點。對于二叉樹來說,要了解它的三種遍歷方式:先序、中序和后序遍歷,并且要掌握好這三者之間的區別以及常見的應用場景。

關于樹在前端中的應用講到這里就結束啦!希望對大家有幫助~

如有疑問或文章有誤歡迎評論區留言或公眾號后臺加我微信提問~

🐣彩蛋One More Thing

(:往期推薦

棧👉棧在前端中的應用,順便再了解下深拷貝和淺拷貝!

隊列👉詳解隊列在前端的應用,深剖JS中的事件循環Eventloop,再了解微任務和宏任務

鏈表👉詳解鏈表在前端的應用,順便再弄懂原型和原型鏈!

字典和集合👉ES6的Set和Map你都知道嗎?一文了解集合和字典在前端中的應用

動態規則和分而治之算法👉一文了解分而治之和動態規則算法在前端中的應用

貪心算法和回溯算法👉一文了解貪心算法和回溯算法在前端中的應用

(:番外篇

  • 關注公眾號星期一研究室,第一時間關注學習干貨,更多精選專欄待你解鎖~
  • 如果這篇文章對你有用,記得留個腳印jio再走哦~
  • 以上就是本文的全部內容!我們下期見!👋👋👋

總結

以上是生活随笔為你收集整理的一文了解树在前端中的应用,掌握数据结构中树的生命线的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产a一区二区三区 | 日韩字幕| 欧美黑人一级 | 又大又粗弄得我出好多水 | 欧美 丝袜 自拍 制服 另类 | www.4虎| 亚洲男人天堂2020 | 国产二页 | 亚洲第一页夜 | 11一12免费毛片 | 免费看黄色一级大片 | 五月在线视频 | 久久久国产精华液999999 | 黄色在线网 | 男人的天堂你懂的 | 成人在线观看一区二区三区 | 亚洲暴爽 | 性生活视频播放 | 免费成人美女在线观看. | 久草热在线视频 | 欧美激情视频一区二区三区不卡 | 欧美日本久久 | 国产极品在线播放 | 久久精品日 | 成人av网站在线观看 | 国产精品久久久久野外 | 美女裸体跪姿扒开屁股无内裤 | 视频免费在线观看 | 91视频在线观看 | 息与子五十路翔田千里 | 久草超碰 | 日本福利小视频 | 99re视频在线播放 | 色婷婷久久综合 | 伊人中文字幕在线观看 | 亚洲精选中文字幕 | 春色校园激情 | 婷婷亚洲激情 | 四虎在线免费观看 | 国产精品77 | 毛片网站入口 | 用舌头去添高潮无码视频 | 欧美a∨亚洲欧美亚洲 | 亚洲天堂第一 | 影音先锋中文字幕在线播放 | 日本精品久久久久中文字幕 | 小宝贝真紧h军人h | 一二区免费视频 | 人人看人人看 | 国产精品77| 黄色在线免费观看 | 男人的av | 91成人在线免费视频 | 国产欧美在线精品日韩 | 欧美亚洲大片 | 一卡二卡在线观看 | 日本一区精品视频 | 亚洲黄色影视 | 精品香蕉99久久久久网站 | 少妇被爽到高潮动态图 | 国产乱人视频 | 在线青草 | 亚洲国产成人在线观看 | sao虎视频在线精品永久 | 亚洲精品6 | 精品蜜桃av | 国产精品99久久久久久大便 | 亚洲一区二区天堂 | 亚洲国产aⅴ精品一区二区的游戏 | 亚洲校园激情 | 青青青国产在线 | 毛片在线播放视频 | 国产精品第3页 | 亚洲人精品 | 色无极亚洲影院 | 国产xxx在线观看 | 欧美三级黄色大片 | 国产精品伦一区二区三区 | 国产一级α片 | 一级欧美视频 | 免费观看一区二区三区视频 | 九九视频在线观看 | 狠狠操91| 白嫩少妇激情无码 | 欧美日韩视频网站 | 精品人妻大屁股白浆无码 | 国产高清精品在线 | 免费在线视频你懂的 | 深夜免费在线视频 | 亚洲1级片 | 美女光屁股视频 | 国产精品国产三级国产aⅴ9色 | 欧亚免费视频 | 都市激情国产精品 | 杨幂毛片 | 日韩网站视频 | 国产污污视频在线观看 | 精品乱 | 婷婷激情电影 |