摘要:本文包括簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)和查找算法,屬于個(gè)人整理。初學(xué)編程可以用這里的東西聯(lián)系一下,看一看也挺有意思博主個(gè)人不認(rèn)為中算法數(shù)據(jù)結(jié)構(gòu)不重要,畢竟這是程序開(kāi)發(fā)的基本功。
本文包括簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)和查找算法,屬于個(gè)人整理。數(shù)據(jù)結(jié)構(gòu)部分 列表
初學(xué)編程可以用這里的東西聯(lián)系一下,看一看也挺有意思
博主個(gè)人不認(rèn)為js中算法數(shù)據(jù)結(jié)構(gòu)不重要,畢竟這是程序開(kāi)發(fā)的基本功。
本文還會(huì)根據(jù)博主學(xué)習(xí)進(jìn)展和時(shí)間安排不定期更新
function List(){ this.listSize = 0; this.pos = 0; this.dataStore = []; //查找 this.find = function(element){ return dataStore.indexOf(element); }; //追加元素 this.append = function(element){ this.dataStore[this.listSize++] = element; }; //刪除元素 this.remove = function(element){ var foundAt = this.find(element); if(foundAt > -1){ this.dataStore.splice(foundAt, 1); --this.listSize; return true; } return false; }; //得到長(zhǎng)度 this.getLength = function(){ return this.listSize; }; //插入元素 this.insert = function(element, after){ var insertPos = this.find(after); if(insertPos > -1){ this.dataStore.splice(insertPos+1, 0, element); ++this.listSize; return true; } return false; }; //清空列表 this.clear = function(){ delete this.dataStore; this.dataStore.length = 0; this.listSize = this.pos = 0; }; //判斷是否包含某元素 this.contains = function(element){ return this.find(element) !== -1; }; //轉(zhuǎn)換為字符串 this.toString = function(){ return this.dataStore.join(","); }; //把指針移到最前 this.front = function(){ this.pos = 0; }; //把指針移到最后 this.end = function(){ this.pos = this.listSize - 1; }; //前移指針 this.prev = function(){ if(this.pos > 0) --this.pos; }; //后移指針 this.next = function(){ if(this.pos < this.listSize - 1) ++this.pos; }; //得到指針當(dāng)前位置 this.currPos = function(){ return this.pos; }; //把指針移到posi this.moveTo = function(posi){ if(posi < this.listSize && posi >= 0){ this.pos = position; return true; } return false; }; //得到當(dāng)前指針位置元素 this.getElement = function(){ return this.dataStore[this.pos]; }; }隊(duì)列
function queue(){ this.dataStore = []; this.enqueue = function(element){ //入隊(duì) this.dataStore.push(element); }; this.dequeue = function(){ //出對(duì) return this.dataStore.shift(); }; this.front(){ //查看隊(duì)首 return this.dataStore[0]; }; this.back(){ //查看隊(duì)尾 return this.dataStore[this.dataStore.length - 1]; }; this.empty = function(){ //清空隊(duì)列 return this.dataStore.length === 0; }; this.getLength = function(){ //得到隊(duì)列長(zhǎng)度 return this.dataStore.length; }; }棧
function Stack(){ this.dataStore = []; this.push = function(element){ //入棧 this.dataStore.push(element); }; this.peek = function(){ //查看棧頂 if(this.dataStore.length > 0) return this.dataStore[this.dataStore.length - 1]; return undefined; }; this.clear = function(){ //清空 this.dataStore.length = 0; }; this.pop = function(){ //出棧 return this.dataStore.pop(); }; this.getLength = function(){ //得到長(zhǎng)度 return this.dataStore.length; }; }鏈表
function Node(element){ //鏈表節(jié)點(diǎn) this.element = element; this.next = null; } function LList(){ this.head = new Node("head"); this.find = function(item){ //查找 var currNode = this.head; while(currNode && currNode.element != item){ currNode = currNode.next; }; return currNode; }; this.insert = function(newElement, item){ //在item之后插入 var newNode = new Node(newElement); var current = this.find(item); if(current === null) { this.append(newElement); return false; } newNode.next = current.next; current.next = newNode; return true; }; this.display = function(){ //輸出列表 var currNode = this.head; while(currNode.next !== null){ console.log(currNode.next.element); currNode = currNode.next; } }; this.remove = function(element){ var currNode = this.head; while(1){ if(currNode.next === null) return false; if(currNode.next.element === element) break; currNode = currNode.next; } currNode.next = currNode.next.next; }; }環(huán)形鏈表
function Node(element){ //鏈表節(jié)點(diǎn) this.element = element; this.next = null; } function LList(){ this.head = new Node("head"); this.head.next = this.head; //成環(huán) this.find = function(item){ //查找 var currNode = this.head; while(currNode.element != item){ if(currNode.next === this.head) return null; currNode = currNode.next; }; return currNode; }; this.insert = function(newElement, item){ //在item之后插入 var newNode = new Node(newElement); var current = this.find(item); newNode.next = current.next; current.next = newNode; }; this.display = function(){ //輸出列表 var currNode = this.head; while(currNode.next !== this.head){ console.log(currNode.next.element); currNode = currNode.next; } }; this.remove = function(element){ //刪除 var currNode = this.head; while(1){ if(currNode.next == this.head) return false; if(currNode.next.element == element) break; currNode = currNode.next; } currNode.next = currNode.next.next; }; }雙向鏈表
function Node(element){ this.element = element; this.next = null; this.previous = null; } function LList(){ this.head = new Node("head"); this.tail = this.head; this.find = function(item){ //查找 var currNode = this.head; while(currNode.element != item){ if(currNode.next === null) return null; currNode = currNode.next; }; return currNode; }; this.insert = function(newElement, item){ //在item之后插入 var newNode = new Node(newElement); var current = this.find(item); newNode.next = current.next; current.next = newNode; current.next.previous = newNode; newNode.previous = current; }; this.display = function(){ //輸出列表 var currNode = this.head; while(currNode.next !== null){ console.log(currNode.next.element); currNode = currNode.next; } }; this.remove = function(item){ //刪除 var currNode = this.find(item); if(currNode){ currNode.previous.next = currNode.next; currNode.next.previous = currNode.previous; currNode.next = null; currNode.previous = null; return true; } return false; }; this.dispReverse = function(){ //反向輸出 var currNode = this.tail; while(currNode.previous !== null){ console.log(currNode.element); currNode = currNode.previous; } }; }字典
function dictionary(){ this.dataStore = []; this.add = function(key, value){ //插入 if(this.find(key)) console.log(""" + key + "" exists"); else this.dataStore[key] = value; }; this.find = function(key){ //查找 return this.dataStore[key]; }; this.remove = function(key){ //刪除 delete this.dataStore[key]; }; this.showAll = function(){ //有序輸出 var keys = Object.keys(this.dataStore).sort(); keys.forEach(function(key){ console.log(key + " -> " + this.dataStore[key]); }); }; this.count = function(){ //計(jì)數(shù) return Object.keys(this.dataStore).length; }; this.clear = function(){ //清除 for(var k in this.dataStore){ if(dataStore.hasOwnPorperty(k)){ delete this.dataStore[k]; } } }; }集合
function Set(){ if(arr){ this.arr = arr.filter(function(item, index) { return arr.indexOf(item) === index; }); } else { this.arr = []; } } Set.prototype.constructor = Set; Myset.prototype.sort = function(fun){ //排序 this.arr.sort(fun); return this; }; Set.prototype.add = function(data){ //添加 if(this.dataStore.indexOf(data) < 0){ this.dataStore.push(data); } return this; }; Set.prototype.show = function(){ //輸出 console.log(this.dataStore.join(",")); return this; }; Set.prototype.remove = function(data){ //刪除 var pos = this.dataStore.indexOf(data); if(pos > -1){ this.dataStore.splice(pos, 1); } return this; }; Set.prototype.size = function(){ //得到當(dāng)前集合大小(元素?cái)?shù)量) return this.dataStore.length; }; Set.prototype.contains = function(data) { //是否包含data return this.dataStore.indexOf(data) > -1; }; Set.prototype.clone = function(){ //復(fù)制當(dāng)前集合 var tempSet = new Set(); for(var i = 0; i < this.size(); ++i) tempSet.add(this.dataStore[i]); return tempSet; }; Set.prototype.union = function(set){ //求并集 var tempSet = this.clone(); for(var i = 0; i < set.size(); ++i){ if(!tempSet.contains(set.dataStore[i])) temp.dataStore.push(set.dataStore[i]); } return tempSet; }; Set.prototype.interSect = function(set){ //求交集 var tempSet = new Set(); for(var i = 0; i < this.size(); ++i){ if(set.contains(this.dataStore[i])) tempSet.add(this.dataStore[i]); } return tempSet; }; Set.prototype.subSet = function(set){ //判斷當(dāng)前集合是否set的子集 if(this.size() > set.size()) return false; else{ for(var i = 0; i < this.size(); ++i){ if(!set.contains(this.dataStore[i])) return false; } } return true; }; this.difference = function(set){ //求差集 this-set var tempSet = new Set(); for(var i = 0; i < this.dataStore.length; ++i){ if(!set.contains(this.dataStore[i])) tempSet.add(this.dataStore[i]); } return tempSet; };哈希表
function HashTable(){ this.table = []; //this.values = []; //當(dāng)key是整數(shù)的時(shí)候可以簡(jiǎn)單的使用simpleHash this.simpleHash = function(data){ //這個(gè)函數(shù)下文不會(huì)用到 var total = 0; for(var i = 0; i < data.length; ++i) total += data.charDodeAt(i); return total % this.table.length; }; //simpleHash()有一個(gè)嚴(yán)重的問(wèn)題:不同字符串可能得到相同hash碼,比如"Raymond"和"Clayton"。 這叫做哈希碰撞(hashing collision) this.betterHash = function(string, arr){ const H = 31; //引入一個(gè)質(zhì)數(shù) var total = 0; for(var i = 0; i < string.length; ++i) total += H * total + string.charCodeAt(i); total = total % arr.length; return parseInt(total); }; this.showDistro = function(){ var n = 0; for(var i = 0; i < this.table.length; ++i){ // if(this.table[i] !== undefined) //線性探針?lè)ㄊ褂眠@個(gè)if if(this.table[i][0] !== undefined) //散列法使用這個(gè)if console.log(i + ": " + this.table[i]); } }; //即使使用了betterHash,也不能保證在所有輸入中不會(huì)一重復(fù)的輸出,因此產(chǎn)生了散列法(separate chaining)和線性探針?lè)?linear probing) //建立散列 this.buildChains = function(){ for(var i = 0; i < this.table.length; ++i) this.table[i] = []; }; //散列法對(duì)應(yīng)put函數(shù) this.put = function(data){ var pos = this.betterHash(data); var index = 0; if(this.table[pos][index] === undefined) this.table[pos][index] = data; else { while(this.table[pos][index] !== undefined) ++index; this.table[pos][index] = data; } }; //散列法對(duì)應(yīng)get函數(shù) this.get = function(key){ var pos = this.betterHash(key); var index = 0; if(this.table[pos][index] === key) return this.table[pos][index + 1]; else { while(this.table[pos][index] !== key) index += 2; return this.table[pos][index + 1]; } return undefined; }; /* //線性探針?lè)▽?duì)應(yīng)put函數(shù) this.put = function(key, data){ var pos = this.betterHash(data); if(this.table[pos] == undefined){ this.table[pos] = key; this.values[pos] = data; } else { while(this.table[pos] != undefined) ++pos; this.table[pos] = key; this.values[pos] = data; } }; //線性探針?lè)▽?duì)應(yīng)get函數(shù) this.get = function(key){ var hash = -1; hash = this.betterHash(key); if(hash > -1){ for(var i = hash; this.table[hash] != undefined; ++i){ if(this.table[hash] == key) return this.values[hash]; } } }; */ }樹(shù)
function Node(data, left, right){ //樹(shù)節(jié)點(diǎn) this.data = data; this.left = left; this.right = right; this.show = function(){ return this.data; }; } //建立一個(gè)二叉查找樹(shù)(Binary Search Tree) function BST(){ this.root = null; this.insert = function(data){ var n = new Node(data, null, null); if(this.root === null) { this.root = n; } else{ var current = this.root; var parent; while(true){ parent = current; if(data < current.data){ current = current.left; if(current === null){ parent.left = n; break; } } else{ current = current.right; if(current == null){ parent.right = n; break; } } } } }; //中序遍歷 this.inOrder = function(node){ if(node !== null){ inOrder(node.left); console.log(node.show() + " "); inOrder(node.right); } }; //前序遍歷 this.preOrder = function(node){ if(node !== null){ console.log(node.show() + " "); preOrder(node.left); preOrder(node.right); } }; //后序遍歷 this.postOrder = function(node){ if(node !== null){ postOrder(node.left); postOrder(node.right); console.log(node.show() + " "); } }; //得最小值 this.getMin = function(){ var current = this.root; while(current.left !== null) current = current.left; return current.data; }; //得最大值 this.getMax = function(){ var current = this.root; while(current.right !== null) current = current.right; return current.data; }; //查找值 function find(data){ var current = this.root; while(current !== null){ if(current.data == data) return current; else if(data < current.data) current = current.left; else if(data > current.data) current = current.right; } return null; }; //刪除值 this.removeData = function(data){ this.root = removeNode(this.root, data); function removeNode(node, data){ if(node === null) return null; if(data === node.data){ if(node.left == null && node.right == null) return null; if(node.left == null) return node.right; if(node.right == null) return node.left; var tempNode = getSmallest(node.right); node.data = tempNode.data; node.right = removeNode(node.right, tempNode.data); return node; } else if(data < node.data){ node.left = removeNode(node.left, data); return node; } else{ node.right = removeNode(node.right, data); return node; } } }; }圖
function Graph(v_num){ this.vertices = v_num; //定點(diǎn)數(shù)量 this.edges = 0; //邊的數(shù)量 this.adj = []; //鄰接矩陣 this.marked = []; //用于遍歷時(shí)標(biāo)記已遍歷的點(diǎn) this.vertexList = []; //存放頂點(diǎn) this.edgeTo = []; //在尋找最短路徑時(shí),存放軌跡 for(var i = 0; i < this.vertices; ++i){ //初始化鄰接矩陣 this.adj[i] = []; this.adj[i] = push(""); } this.addEdge = function(v, w){ //添加邊,傳入2個(gè)點(diǎn) this.adj[v].push(w); this.adj[w].push(v); this.edges++; }; this.showGraph = function(){ //輸出圖 for(var i = 0; i < this.vertices; ++i){ console.log(i + " -> "); for(var j = 0; j < this.vertices; ++j){ if(this.adj[i][j] !== undefined) console.log(this.adj[i][j] + " "); } console.log(" "); } }; //深度優(yōu)先遍歷 this.dfs = function(v){ for(var i = 0; i < this.vertices; ++i) //初始化標(biāo)記矩陣 this.mark[i] = false; innerDfs(v); function innerDfs(v){ this.marked[v] = true; if(this.adj[v] !== undefined) console.log(v + " "); for(var i = 0; i < this.adj[v].length; ++i){ var ver = this.adj[v][i]; if(!this.marked[ver]) this.innerDfs(ver); } } }; //廣度優(yōu)先遍歷 this.bfs = function(s){ for(var i = 0; i < this.vertices; ++i) //初始化標(biāo)記矩陣 this.mark[i] = false; var queue = []; //存放訪問(wèn)過(guò)的節(jié)點(diǎn) this.marked[s] = true; queue.push(s); while(queue.length > 0){ var v = queue.shift(); if(v !== undefined) console.log(s + ""); for(var i = 0; i < this.adj[v].length; ++i){ var ver = this.adj[v][i]; if(!this.marked[ver]){ this.edgeTo[ver] = v; this.marked[ver] = true; queue.push(ver); } } } }; this.hasPathTo = function(v){ //判斷是否有到節(jié)點(diǎn)v的路徑 return this.marked[v]; }; this.showPath = function(){ //顯示路徑 while(paths.length > 0){ if(paths.legnth > 1) console.log(paths.pop() + "-"); else console.log(paths.pop()); } }; this.pathTo = function(v) { //計(jì)算path路徑 var path = []; var source = 0; if(!this.hasPathTo(v)) return undefined; for(var i = v; i !== source; i = this.edgeTo[i]) path.push(i); path.push(source); return path; }; //拓?fù)渑判? this.topologicalSort = function(){ var stack = []; //棧 var visited = []; //記錄已訪問(wèn)節(jié)點(diǎn) //初始化 for(var i = 0; i < this.vertices; ++i) visited = false; for(var i = 0; i < this.vertices; ++i){ if(!visited[i]) this.topSortHelper(i, visited); //排列沒(méi)有訪問(wèn)過(guò)的節(jié)點(diǎn) } for(var i = 0; i < stack.length; ++i){ if(stack[i] !== undefined && stack[i] !== false) console.log(this.vertexList[stack[i]]); } function topSortHelper(v, visited){ visit[v] = true; for(var i = 0; i < this.adj[v].length; ++i){ var w = this.adj[v][i]; if(!visited[w]) this.topSortHelper(visited[w], visited); //遞歸當(dāng)前節(jié)點(diǎn)的相鄰節(jié)點(diǎn) } stack.push(v); } }; }查找相關(guān)算法 順序查找
function seqSearch(arr, data){ for(var i = 0; i < arr.length; i++){ if(arr[i] == data) return i; } return -1; }二分查找
//數(shù)組arr應(yīng)該已升序排列 function binSearch(arr, data){ var upperBound = arr.length - 1; var lowerBound = 0; while(lowerBound <= upperBound){ var mid = Math.floor((upperBound + lowerBound) / 2); if(arr[mid] < data) lowerBound = mid + 1; if(arr[mid] > data) upperBound = mid - 1; if(arr[mid] == data) return mid; } return -1; } //利用二分查找計(jì)數(shù) //數(shù)組arr應(yīng)該已升序排列 function count(arr, data){ var count = 0; var pos = binSearch(arr, data); if(pos > -1){ ++count; for(var i = pos - 1; i > 0; --i){ if(arr[i] == data) ++count; else break; } for(var i = pos + 1; i < arr.length; ++i){ if(arr[i] == data) ++count; else break; } } return count; }二叉查找樹(shù)
在本文數(shù)據(jù)結(jié)構(gòu)部分——樹(shù)的部分已經(jīng)實(shí)現(xiàn)
哈希查找在本文數(shù)據(jù)結(jié)構(gòu)部分——哈希表部分的get()方法已經(jīng)實(shí)現(xiàn)
插值查找function insertionSearch(arr, value){ return insertionSearchHelper(arr, value, 0, arr.length); function insertionSearchHelper(arr, value, low, high){ var mid = low + (value - arr[low]) / (arr[high] - arr[low]) * (high - low); if(arr[mid] === value) return mid; if(arr[mid] > value) return InsertionSearchHelper(arr, value, low, mid-1); if(arr[mid] < value) return InsertionSearchHelper(arr, value, mid+1, high); return null; } }
整理所有查找算法時(shí)間復(fù)雜度
算法 | 查找(最壞) | 插入(最壞) | 刪除(最壞) | 查找(最好) | 插入(最好) | 刪除(最好) | 是否要求有序 |
---|---|---|---|---|---|---|---|
順序結(jié)構(gòu) | N | N | N | $frac{N}{2}$ | N | $frac{N}{2}$ | No |
二分算法 | logN | N | N | logN | $frac{N}{2}$ | $frac{N}{2}$ | Yes |
二叉查找樹(shù)(BST) | N | N | N | 1.39logN | 1.39logN | $sqrt{N}$ | Yes |
2-3樹(shù) | clogN | clogN | clogN | clogN | clogN | clogN | Yes |
紅黑樹(shù) | 2logN | 2logN | 2logN | logN | logN | logN | Yes |
哈希散列查找 | logN | logN | logN | 3~5 | 3~5 | 3~5 | No |
哈希探針查找 | logN | logN | logN | 3~5 | 3~5 | 3~5 | No |
平均查找長(zhǎng)度(ASL) = 查找表中第 $i$ 個(gè)元素概率($P_i$) $ imes$ 找到第 $i$ 個(gè)元素時(shí)已經(jīng)比較的次數(shù)($C_i$)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97455.html
摘要:數(shù)據(jù)結(jié)構(gòu)程序數(shù)據(jù)結(jié)構(gòu)算法數(shù)據(jù)結(jié)構(gòu)基本概念數(shù)據(jù)的邏輯結(jié)構(gòu)反映數(shù)據(jù)元素之間的關(guān)系的數(shù)據(jù)元素集合的表示。這兩部分信息組成數(shù)據(jù)元素的存儲(chǔ)映象,稱(chēng)為結(jié)點(diǎn)。 本文涉及更多的是概念,代碼部分請(qǐng)參考之前寫(xiě)過(guò)的 2 篇博客 基于 Javascript 的排序算法 基于 javascript 的基本數(shù)據(jù)結(jié)構(gòu)和查找算法 本文主要是基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)和算法概念,可能部分地方會(huì)涉及更高級(jí)的算法和算法,具體內(nèi)容以...
摘要:數(shù)據(jù)項(xiàng)是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項(xiàng)是對(duì)客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對(duì)象是性質(zhì)相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個(gè)子集。數(shù)據(jù)的邏輯結(jié)構(gòu)數(shù)據(jù)元素之間的相互關(guān)系稱(chēng)為邏輯結(jié)構(gòu)。 項(xiàng)目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡(jiǎn)...
摘要:數(shù)據(jù)項(xiàng)是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項(xiàng)是對(duì)客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對(duì)象是性質(zhì)相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個(gè)子集。數(shù)據(jù)的邏輯結(jié)構(gòu)數(shù)據(jù)元素之間的相互關(guān)系稱(chēng)為邏輯結(jié)構(gòu)。 項(xiàng)目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡(jiǎn)...
摘要:數(shù)據(jù)項(xiàng)是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項(xiàng)是對(duì)客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對(duì)象是性質(zhì)相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個(gè)子集。數(shù)據(jù)的邏輯結(jié)構(gòu)數(shù)據(jù)元素之間的相互關(guān)系稱(chēng)為邏輯結(jié)構(gòu)。 項(xiàng)目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡(jiǎn)...
摘要:因此,根據(jù)題目給出的先序遍歷和中序遍歷,可以畫(huà)出二叉樹(shù)選參考數(shù)據(jù)結(jié)構(gòu)與算法描述實(shí)現(xiàn)二叉樹(shù)算法淺談數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)慕課網(wǎng)實(shí)現(xiàn)二叉樹(shù)算法前端樹(shù)控件騰訊軟件開(kāi)發(fā)面試題 內(nèi)容銜接上一章 數(shù)據(jù)結(jié)構(gòu)與算法:常見(jiàn)排序算法 內(nèi)容提要 什么是樹(shù) - 為什么使用樹(shù) 二叉樹(shù) 二叉查找樹(shù) 紅黑樹(shù) B、B+樹(shù) 堆 伸展樹(shù) 樹(shù) 可以點(diǎn)擊鏈接感受下筆者用d3.js畫(huà)的tree https://codepen...
閱讀 2918·2021-11-23 09:51
閱讀 3443·2021-11-22 09:34
閱讀 3338·2021-10-27 14:14
閱讀 1548·2019-08-30 15:55
閱讀 3371·2019-08-30 15:54
閱讀 1103·2019-08-30 15:52
閱讀 1918·2019-08-30 12:46
閱讀 2872·2019-08-29 16:11