中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

甘肅購物網(wǎng)站建設軟件定制開發(fā)公司

甘肅購物網(wǎng)站建設,軟件定制開發(fā)公司,知名餐飲設計公司,杭州公司展廳設計公司C 表情包趣味教程 👉 《C要笑著學》 💭 寫在前面:半年沒更 C 專欄了,上一次更新還是去年九月份,被朋友催更很久了hhh 本章倒回數(shù)據(jù)結構專欄去講解搜索二叉樹,主要原因是講解 map 和 set 的特性需要二叉搜索…

???C++?表情包趣味教程?👉?《C++要笑著學》

💭 寫在前面半年沒更?C++ 專欄了,上一次更新還是去年九月份,被朋友催更很久了hhh

本章倒回數(shù)據(jù)結構專欄去講解搜索二叉樹,主要原因是講解 map 和 set 的特性需要二叉搜索樹做鋪墊,理解搜索二叉樹有助于更好地理解 map 和 set 的特性。第二個原因是為了后期講解查找效率極高的平衡搜索二叉樹,隨后再講完紅黑樹,我們就可以模擬實現(xiàn) map 和 set 了。二叉樹的基礎知識講解在我的《樹鋸結構》專欄中有寫,這里放上鏈接方便復習。

🔗 復習鏈接:【數(shù)據(jù)結構】二叉樹的遍歷


Ⅰ. 搜索二叉樹(SearchBinaryTree)

0x00 搜索二叉樹的概念

📚 概念:搜索二叉樹又稱為二叉排序樹,它或者是一顆空樹,或者是具有以下性質(zhì)的二叉樹:

  • 若其左子樹不是空,則左子樹上所有節(jié)點的值都小于根結點的值
  • 若其右子樹不是空,則右子樹上所有結點的值都大于根結點的值
  • 其左右子樹必須都是二叉搜索樹

??

至于叫它 "搜索二叉樹",還是 "二叉搜索樹",這個似乎也沒有特別的規(guī)定,應該都是可以的。

但我更喜歡叫它?"搜索二叉樹",因為這樣翻譯過來是 "Search Binary Tree",

?但是我并不是因為這樣可以叫它 SB?樹才喜歡的。

(而且這樣也不文明,而且已經(jīng)有 SB 樹了,Size Balanced Tree)

而是因為? 叫?"搜索二叉樹 Search Binary Tree" 可以順便記住它的性質(zhì):

Search Binary TreeS 也可以表示?SmallB?也可以表示 Big,SB 即左邊小右邊大!

(一般而言,搜索二叉樹都是左邊小右邊大的)

?這樣可以正好能對應它的性質(zhì):左子樹的值 < 根?< 右子樹的值

🔺 結論:任意一個子樹都需要滿足,左子樹的值 < 根?< 右子樹的值,才能構成二叉搜索樹。?

0x01 搜索二叉樹的優(yōu)勢

既然叫搜索二叉樹,它肯定是用來搜索的,當滿足搜索二叉樹時你將可以快速地查找任意的值。

💭 舉個例子:?查找?7

放到以前我們?nèi)绻挥枚植檎?#xff0c;可能會選擇用暴力的方式去從頭到尾遍歷一遍。

但現(xiàn)在學了搜索二叉樹,我們就可以輕松找到這個?7?了,不信你看:

STEP1:7?比?8?(根節(jié)點) 小,根據(jù)搜索二叉樹的性質(zhì),它必然不會出現(xiàn)在右子樹 (右邊大) !

?所以,直接 🔒?鎖定?左子樹開始找:

STEP2:?7?比 3?大,根據(jù)性質(zhì)它肯定不會出現(xiàn)在左子樹 (左邊小) !

?這次,直接?🔒鎖定 右子樹繼續(xù)找:?

STEP3:?我們繼續(xù)對比,7?比?6?大,所以在右邊,就這么輕輕松松的找到了:

?搜索二叉樹查找一個值的最壞情況,也只是查找高度次。?你就說爽不爽吧。

這就是搜索二叉樹,它的搜索功能是真的名副其實的厲害!

0x02?二叉搜索樹的時間復雜度:O(N)

上面的例子舉得太絲滑了,會讓人誤以為搜索二叉樹的時間復雜度是?O(logN)?……

但實際上是?O(N)? !!!

因為這棵樹是有可能會 蛻化 的,極端情況下會蛻化成一個 "單邊樹" :

??

😢 最差情況:二叉搜索樹退化為單邊樹(或類似單邊),其平均比較次數(shù)為:

O(\frac{N}{2})\Rightarrow O(N)

?但是在好的情況下,其搜索效率也是非??捎^的:

😍 最優(yōu)情況:二叉搜索樹為完全二叉樹(或接近完全二叉樹),其平均比較次數(shù)為:

O(log_2N)\Rightarrow O(logN)

? 對于時間復雜度的分析我們要做一個悲觀主義者,根據(jù)最差情況去定時間復雜度。

🔺 總結:搜索二叉樹的時間復雜度為?O(N)

0x03 搜索二叉樹的改良方案

?如果搜索二叉樹蛻化成了單邊樹,其性能也就失去了,能否進行改進讓它保持性能?

如何做到不論按照上面次序插入關鍵碼,二叉搜索樹的性能均能達到最優(yōu)?

搜索二叉樹由于控制不了極端情況,與?O(logN)?失之交臂,但平衡二叉搜索樹做到了。

"平衡二叉樹的搜索效率極高"

嚴格意義上來說滿二叉樹才是?O(logN),完全二叉樹是接近?O(logN)?。

而平衡搜索二叉樹維持左右兩邊均勻程度,讓它接近完全二叉樹,從而讓效率趨近?O(logN)。

Ⅱ.?搜索二叉樹的實現(xiàn)

0x00 搜索二叉樹的定義

?搜索二叉樹,SearchBinaryTree 名稱實在是又臭又長!

我們不如取名為 SBTree,但是 SBTree 聽起來好像有點不文明,我們還是叫 BSTree 吧。

這里我們用模板,模板參數(shù)我們給了一個 K,表示 key 的意思(模板參數(shù)并非一定要用 T)

template<class K> 
struct BSTreeNode {BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key): _left(nullptr), _right(nullptr), _key(key) {}
};

下面我們來定義整個樹,BSTreeNode 也有些長了,我們不如將其 typedef Node?。

這里我們構造函數(shù)都沒必要寫,它自己生成的就夠用了:

template<class K> 
class BSTree {typedef BSTreeNode<K> Node;
private:Node* _root = nullptr;    // 懶得寫構造函數(shù)了
};

0x01?搜索二叉樹的插入

?我們先來實現(xiàn)最簡單的插入操作:

  • 如果樹為空,則直接新增結點,賦值給 root 指針。
  • 如果樹不為空,按二叉搜索樹性質(zhì)查找插入位置,插入新節(jié)點。
bool Insert(const K& key);

Insert 的實現(xiàn)我們可以用遞歸,也可以用非遞歸,這一塊遞歸比非遞歸更難理解。

秉著先難后易的態(tài)度,我們先講比較難理解的非遞歸版本!

💡 分析

Step1:首先檢查是否有根結點 _root,如果沒有我們就 new 一個結點出來作為根結點。
此時插入成功,返回 true。

Step2:插入就需要找到插入位置,我們定義一個 cur 變量,從根節(jié)點開始,
根據(jù)搜索二叉樹 "SB" 性質(zhì),將 cur 結點的值與插入的值 x?進行大小比較。

  • 如果插入的值大于當前結點值,則將 cur 結點向右移動?cur=cur->_right?;
  • 如果插入的值小于當前節(jié)點值,就將 cur 結點向左移動 cur=cur->_left。

值得注意的是,我們還需要額外記錄一下 cur 的父結點,因為你不知道什么時候會碰?\textrm{null} 結束。
并且當我們找到插入位置后,僅僅 new 上一個新結點給 cur 是完成不了插入操作的!
因為直接這么做 cur 也只是一個局部變量而已,你需要?cur 跟上一層(cur 的父親)相鏈接才行!
為了能找到上一層,所以我們還需要額外定義一個 prev 變量來記錄 cur 的父結點,
在我們更換 cur 結點時記錄父結點的位置 prev=cur?即可。
當然了,還有一種插入失敗的情況,就是判斷大小時出現(xiàn)等于的情況,返回 false 即可。
(重復的值是不允許插入的,默認情況是不允許冗余的!但是也有針對這個的變形,后續(xù)再說)

Step3:插入!new 一個新結點給 cur,此時 cur 只是一個局部變量,必須要和父親鏈接,
此時應該鏈接父親的左邊,還是鏈接父親的右邊?我們不知道,所以我們需要再做一個比較!

  • 如果父節(jié)點的值大于插入的值,則將 cur 鏈接到父親左邊 prev->_left=cur
  • 反之將 cur 鏈接到父親右邊? prev->_right=cur。

最后,插入成功返回?true,我們的插入操作就大功告成了。

💬 代碼演示:Insert 接口的實現(xiàn)

/* 插入 */
bool Insert(const K& x) {/* 檢查是否由根節(jié)點 */if (_root == nullptr) {    // 如果根節(jié)點為空指針_root = new Node(x);   // 創(chuàng)建一個新結點作為根結點return true;           // 插入成功,返回真}Node* prev = nullptr;      // 用于記錄cur的父親Node* cur = _root;         // 從根節(jié)點開始/* 找到插入位置 */while (cur != nullptr) {if (x > cur->_key) {          // 如果插入的值大于當前結點值,則向右移動prev = cur;               // 保存父節(jié)點cur = cur->_right;        // 令cur右滑}else if (x < cur->_key) {     // 如果插入的值小于當前結點值,則向左移動prev = cur;      cur = cur->_left;         // 令cur左滑}else {                        // 相等的情況,禁插return false;             // 插入失敗,返回假}}/* 插入位置已找到,準備進行鏈接操作 */cur = new Node(x);      // 創(chuàng)建一個新結點,賦給cur,此時cur為局部,需與父結點鏈接if (prev->_key > x) {   // 如果父結點的值大于插入的值,則將cur鏈接到左邊prev->_left = cur;} else {                  // 如果父節(jié)點的值小于插入的值,則將cur鏈接到右邊prev->_right = cur;}return true;   // 插入成功,返回真
}

再寫一個中序遍歷來測試一下插入的效果:

void InOrder(Node* root) {if (root == nullptr) {return;}InOrder(root->_left);            // 左cout << root->_key << " ";       // 值InOrder(root->_right);           // 右
}

模擬出一個測試用例:

void TestBSTree() {BSTree<int> t;int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };for (auto e : a) {t.Insert(e);}t.InOrder();  ? 沒法傳根
}

此時會出現(xiàn)一個問題,因為根是私有的,我們沒辦法把根傳過去。

此時我們可以選擇在類內(nèi)部寫一個成員函數(shù) GetRoot 去取根,但是這里我們可以選擇這么做:

	void InOrder() {_InOrder(_root);}private:// 改為內(nèi)部函數(shù)void _InOrder(Node* root) {if (root == nullptr) {return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}Node* _root = nullptr;
};

干脆將剛才我們實現(xiàn)的中序設為 private 私有,然后再寫一個 InOrder 放在公有的區(qū)域。

這就是在類內(nèi)訪問 _root 了,沒有什么問題。

如此一來我們在類外就可以直接調(diào)用 InOrder,并且也不需要傳遞參數(shù)了。

int main(void)
{TestBSTree();return 0;
}

🚩 運行結果:

0x02 搜索二叉樹的查找

?find 實現(xiàn)很容易,用和剛才一樣的思路,從根結點開始查找。?

從根開始,如果要查找的值大于 cur 目前的值,則讓 cur 往右走,反之往左走。

當查找得值與 cur 的值相等時則說明找到了,返回 true

cur 觸及到空(while 循環(huán)結束)則說明找不到,返回 false。

💬 代碼實現(xiàn):搜索二叉樹的查找

/* 查找 */
bool Find(const K& target) {Node* cur = _root;                    // 從根結點開始查找while (cur != nullptr) {      if (target > cur->_key) {         // 如果目標值比當前結點值大,cur↘cur = cur->_right;       }else if (target < cur->_key) {    // 如果目標值比當前結點值小,cur↙cur = cur->_left;}else {                            // 如果目標值等于結點值,說明找到了/* 找到了,返回真 */return true;}}/* 沒找到,返回假 */return false;
}

0x03 搜索二叉樹刪除

搜索二叉樹真正困難的是刪除,搜索二叉樹刪除的實現(xiàn)是有很有難度的。

刪除的實現(xiàn)就需要一些 "奇技淫巧" 了,斷然刪除會毀樹。

沒有孩子或者只有一個孩子,可以直接刪除,孩子托管給父親。

兩個還是沒辦法給父親,父親養(yǎng)不了這么多孩子,但是可以找個人替代父親養(yǎng)孩子。

當然,也不能隨便找,找的人必須仍然維持搜索二叉樹的性質(zhì),這是原則。

"你不能說搞得我都不是搜索二叉樹了,那還玩?zhèn)€錘子"

必須比左邊的大,比右邊的小。所以在家族中找是最合適的。

找左子樹的最大值結點,或者右子樹的最小值結點。

首先要查找元素是否在二叉搜索樹中,如果不存在,則返回。

如果存在,那么刪除的結點可能分為下面四種情況:

a. 要刪除的結點無孩子結點
b. 要刪除的結點只有左孩子結點
c. 要刪除的結點只有右孩子結點
d. 要刪除的結點有左孩子結點也有右孩子結點

看起來有待刪除節(jié)點有 4 種情況,但實際上 a 和 b,或 a 和 c 可以合并。

📌 因此,真正的刪除過程如下:

  • 情況B:刪除該結點且使被刪除結點的父結點指向被刪除節(jié)點的左孩子結點 —— 直接刪除。
  • 情況C:刪除該節(jié)點且使被刪除結點的父節(jié)點指向被刪除節(jié)點的右孩子結點 —— 直接刪除。
  • 情況D:在它的右子樹中尋找中序下的第一個結點(值最小),用它的值填補到被刪除結點中,再來處理該結點的刪除問題 —— 替換法刪除。

① 該結點無左孩子

如果要刪除下面這顆二叉樹的 10 節(jié)點和 4 節(jié)點:

我們還是定義一個 cur 變量,當 cur 找到 10 結點后,如果左側為空情況如下:

  1. 若該結點為 root,直接讓 root 等于它的右孩子結點。
  2. 對于刪除 10 結點:若 cur==father->right,則令?parent->right = cur->right (如圖所示)
  3. 對于刪除 4 結點:若 cur==father->left,則令 parent->left=cur->right (如圖所示)
  4. 最后刪除 cur 結點

💬 代碼演示:

if (cur->_left == nullptr) {/* 判斷要刪除的結點是否為根結點 */if (cur == _root) {_root = cur->_right;}else {if (cur == father->_right) {/* 如果 cur 比 father 大 */father->_right = cur->_right;}else {father->_left = cur->_right;}}delete cur;cur = nullptr;
}

② 該結點無右孩子

?如果要刪除 14 結點,刪除邏輯和刪除左孩子是類似的:

💬 代碼演示:

else if (cur->_right == nullptr) {/* 判斷是否為根結點 */if (cur == _root) {_root = cur->_left;}else {if (cur == father->_right) {/* cur 比父結點大 */father->_right = cur->_left;}else {father->_left = cur->_left;}}delete cur;cur = nullptr;
}

③ 該結點有左右兩個孩子

如果刪除的結點有左右兩個孩子,我們就在它的右子樹中尋找中序的第一個結點。

與右子樹的最小值進行替換,當然也可以選擇左子樹的最大值進行替換。

💭 例子:比如下面這顆子樹,我們要刪除 3 結點:

如果該結點有兩個孩子,則采用如下替換法:

該結點和右子樹的最小值或左子樹的最大值進行值的替換,然后刪除替換后的結點。

這里我們采用與右子樹的最小值進行替換。

💬 代碼演示:非遞歸版本的 Erase

bool Erase(const K& key) {Node* father = nullptr;Node* cur = _root;while (cur != nullptr) {if (cur->_key < key) {father = cur;cur = cur->_right;}else if (cur->_key > key){father = cur;cur = cur->_left;}else {/* 找到了! 情況一:該節(jié)點沒有左孩子   情況二:該節(jié)點沒有右孩子 */if (cur->_left == nullptr) {/* 判斷是否為根結點 */if (cur == _root) {_root = cur->_right;}else {if (cur == father->_right) {//cur 比 father大father->_right = cur->_right;}else {father->_left = cur->_right;}}delete cur;cur = nullptr;}else if (cur->_right == nullptr) {/* 判斷是否為根結點 */if (cur == _root) {_root = cur->_left;}else {if (cur == father->_right) {/* 如果 cur 比父結點大 */father->_right = cur->_left;}else {father->_left = cur->_left;}}delete cur;cur = nullptr;}else {/* 有兩個節(jié)點,替換 */Node* MinParNode = cur;Node* MinNode = cur->_right;while (MinNode->_left) {MinParNode = MinNode;MinNode = MinNode->_left;}swap(cur->_key, MinNode->_key);if(MinParNode->_left == MinNode) {MinParNode->_left = MinNode->_right;}else {MinParNode->_right = MinNode->_right;}delete MinNode;MinNode = nullptr;}return true;}}return false;
}

💡 解讀:找到 3 結點中右子樹的最小結點,替換它們的值。定義 MinParNode 為 cur,MinNode 為 cur 的右節(jié)點。首先讓 MinNode 指向 3 的右孩子(1),然后一直向左邊找知道找到 nullptr 為止,此時 MinNode 指向的就是最小的結點了,此時讓 3 與 MinNode 的值交換即可。

交換后,刪除 3 就變成了刪除 MinNode,我們需要弄清 MinNode? 和 MinParNode 的指向關系:

  • 如果 MinParNode 的左孩子是 MinNode,則讓 MinParNode 的左指向 MinNode 的右。
  • 如果 MinParNode 的右孩子是 MinNode,則讓 MinParNode 的右指向 MinNode 的右。(這里讓 MinParNode 指向 MinNode 的右的原因是?MinNode 已是最小結點,不可能有左孩子了)

Ⅲ. 搜索二叉樹的應用

0x00 K 模型

K?模型,即只有 key?作為關鍵碼,結構中只需存儲 key?即可,關鍵碼就是需要搜索到的值。

💭 舉個例子:對于單詞 word,我們需要判斷該單詞是否拼寫正確

  • 以單詞集合中的每個單詞作為 key,構建一個搜索二叉樹。
  • 在二叉樹中檢索該單詞是否存在,存在則拼寫正確,不存在則拼寫錯誤。

0x01 KV 模型

KV?模型,每一個關鍵碼 key,都有與之對應的值 Value,即 <Key, Value> 的鍵值對。

這就像 Python 中的 dict 字典類型一樣,key 和 value 對應。

這在生活中也是非常常見的,比如英漢詞典就是英文與中文的對應關系,通過英文可以快讀檢索到對應的中文,英文單詞也可以與其對應的中文構建出一種鍵值對:

<word, chinese>

再比如統(tǒng)計單詞次數(shù),統(tǒng)計成功后,給定的單詞就課快速找到其出現(xiàn)的次數(shù),單詞與其出現(xiàn)的次數(shù)就構建出了一種鍵值對:

<word, count>

💬 代碼演示:我們實現(xiàn)一個簡單的英漢詞典 dict,可以通過英文找到對應的中文。

具體實現(xiàn)方式如下:

  • <單詞, 中文含義>? 以鍵值對構造搜索二叉樹,值得注意的是,搜索二叉樹需要比較,鍵值對比較時只比較 Key。
  • 查詢英文單詞時,只需給出英文單詞,就可以快速檢索到對應的 Key
namespace KV
{template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;//pair<K, V> _kv;BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>struct BSTree{typedef BSTreeNode<K, V> Node;public:BSTree():_root(nullptr){}bool Insert(const K& key, const V& value){if (_root == nullptr){_root = new Node(key, value);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key, value);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return cur;}}return nullptr;}bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{// 找到,準備開始刪除if (cur->_left == nullptr){if (parent == nullptr){_root = cur->_right;}else{if (parent->_left == cur)parent->_left = cur->_right;elseparent->_right = cur->_right;}delete cur;}else if (cur->_right == nullptr){if (parent == nullptr){_root = cur->_left;}else{if (parent->_left == cur)parent->_left = cur->_left;elseparent->_right = cur->_left;}delete cur;}else{Node* minParent = cur;Node* min = cur->_right;while (min->_left){minParent = min;min = min->_left;}cur->_key = min->_key;cur->_value = min->_value;if (minParent->_left == min)minParent->_left = min->_right;elseminParent->_right = min->_right;delete min;}return true;}}return false;}void InOrder(){_InOrder(_root);cout << endl;}private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root;};void TestBSTree1(){// 字典KV模型BSTree<string, string> dict;dict.Insert("sort", "排序");dict.Insert("left", "左邊");dict.Insert("right", "右邊");dict.Insert("map", "地圖、映射");//...string str;while (cin>>str){BSTreeNode<string, string>* ret = dict.Find(str);if (ret){cout << "對應中文解釋:" << ret->_value << endl;}else{cout << "無此單詞" << endl;}}}void TestBSTree2(){// 統(tǒng)計水果出現(xiàn)次數(shù)string arr[] = { "蘋果", "西瓜","草莓", "蘋果", "西瓜", "蘋果", "蘋果", "西瓜", "蘋果", "香蕉", "蘋果", "香蕉" };BSTree<string, int> countTree;for (auto& str : arr){//BSTreeNode<string, int>* ret = countTree.Find(str);auto ret = countTree.Find(str);if (ret != nullptr){ret->_value++;}else{countTree.Insert(str, 1);}}countTree.InOrder();}
}


📌 [ 筆者 ]? ?王亦優(yōu)
📃 [ 更新 ]? ?2023.4.8
? [ 勘誤 ]?? /* 暫無 */
📜 [ 聲明 ]? ?由于作者水平有限,本文有錯誤和不準確之處在所難免,本人也很想知道這些錯誤,懇望讀者批評指正!

📜 參考資料?

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

比特科技. C++[EB/OL]. 2021[2021.8.31].?

http://www.risenshineclean.com/news/51734.html

相關文章:

  • h5響應式網(wǎng)站做動畫百度seo推廣價格
  • 東莞疫情什么時候開始的seo優(yōu)化費用
  • 寧波制作網(wǎng)站企業(yè)有哪些廣東百度seo
  • 受歡迎的網(wǎng)站開發(fā)西安網(wǎng)站建設哪家好
  • 良鄉(xiāng)網(wǎng)站建設網(wǎng)絡營銷案例分析題及答案
  • 花萬元請人做網(wǎng)站推廣引流平臺app大全
  • js做網(wǎng)站好嗎千鋒教育培訓機構地址
  • 微信網(wǎng)站頁面設計深圳整站全網(wǎng)推廣
  • wordpress轉織夢seo搜索引擎優(yōu)化實戰(zhàn)
  • 合優(yōu)做網(wǎng)站需要多少錢百度推廣頁面投放
  • 站長工具查詢網(wǎng)站信息北京網(wǎng)站優(yōu)化多少錢
  • 昆山做網(wǎng)站的kamese百度品牌專區(qū)
  • 有沒關于做動畫設計師的網(wǎng)站臺灣新聞最新消息今天
  • 自己做的網(wǎng)站如何讓別的網(wǎng)可以查看seo賺錢暴利
  • 北京開發(fā)網(wǎng)站上海有哪些優(yōu)化網(wǎng)站推廣公司
  • 網(wǎng)站怎么做的防采集此網(wǎng)站三天換一次域名
  • 網(wǎng)站換模板影響全網(wǎng)整合營銷外包
  • 網(wǎng)站注冊賬號怎么做百度網(wǎng)址鏈接是多少
  • 做網(wǎng)站的怎么認證微博短視頻seo營銷系統(tǒng)
  • 畢設做桌面軟件還是網(wǎng)站優(yōu)化seo公司哪家好
  • 想做電商需要投資多少錢seo資料
  • php網(wǎng)站開發(fā)筆試題百度競價排名正確解釋
  • 可提供獨立站建站服務的公司寧波網(wǎng)站優(yōu)化公司價格
  • 網(wǎng)站怎么做效果更好天橋區(qū)seo全網(wǎng)宣傳
  • 六一兒童節(jié)網(wǎng)站制作北京百度seo排名點擊器
  • c 做asp.net網(wǎng)站西安seo建站
  • 網(wǎng)站建設新方向開魯網(wǎng)站seo不用下載
  • 做編程的網(wǎng)站有哪些方面廣告公司注冊
  • 在那個網(wǎng)站做直播好賺錢百度指數(shù)與百度搜索量
  • wordpress 企業(yè)站 模板網(wǎng)絡廣告的優(yōu)勢有哪些