漫畫講解C語言中最近公共祖先的三種類型
更新時(shí)間:2021年11月24日 09:06:22 作者:2021dragon
這篇文章主要總結(jié)了使用C語言查找最近公共祖先的三種方法類型,用漫畫的方式講解原理定義,看上去更生動形象,幫助你更好的理解透徹,快來跟著本文往下看吧
最近公共祖先定義
查找最近公共祖先
三叉鏈
代碼如下:
//三叉鏈 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode *parent; TreeNode(int x) : val(x), left(NULL), right(NULL), parent(NULL) {} }; class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { TreeNode* curp = p, *curq = q; //用于遍歷p、q結(jié)點(diǎn)的祖先結(jié)點(diǎn) int lenp = 0, lenq = 0; //分別記錄p、q結(jié)點(diǎn)各自的祖先結(jié)點(diǎn)個(gè)數(shù) //統(tǒng)計(jì)p結(jié)點(diǎn)的祖先結(jié)點(diǎn)個(gè)數(shù) while (curp != root) { lenp++; curp = curp->parent; } //統(tǒng)計(jì)q結(jié)點(diǎn)的祖先結(jié)點(diǎn)個(gè)數(shù) while (curq != root) { lenq++; curq = curq->parent; } //longpath和shortpath分別標(biāo)記祖先路徑較長和較短的結(jié)點(diǎn) TreeNode* longpath = p, *shortpath = q; if (lenp < lenq) { longpath = q; shortpath = p; } //p、q結(jié)點(diǎn)祖先結(jié)點(diǎn)個(gè)數(shù)的差值 int count = abs(lenp - lenq); //先讓longpath往上走count個(gè)結(jié)點(diǎn) while (count--) { longpath = longpath->parent; } //再讓longpath和shortpath同時(shí)往上走,此時(shí)第一個(gè)相同的結(jié)點(diǎn)便是最近公共祖先結(jié)點(diǎn) while (longpath != shortpath) { longpath = longpath->parent; shortpath = shortpath->parent; } return longpath; //返回最近公共祖先結(jié)點(diǎn) } };
二叉搜索樹
代碼如下:
//搜索二叉樹 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if (p->val == root->val || q->val == root->val) //p、q結(jié)點(diǎn)中某一個(gè)結(jié)點(diǎn)的值等于根結(jié)點(diǎn)的值,則根結(jié)點(diǎn)就是這兩個(gè)結(jié)點(diǎn)的最近公共祖先 return root; if (p->val < root->val&&q->val < root->val) //p、q結(jié)點(diǎn)的值都小于根結(jié)點(diǎn)的值,說明這兩個(gè)結(jié)點(diǎn)的最近公共祖先在該樹的左子樹當(dāng)中 return lowestCommonAncestor(root->left, p, q); else if (p->val > root->val&&q->val > root->val) //p、q結(jié)點(diǎn)的值都大于根結(jié)點(diǎn)的值,說明這兩個(gè)結(jié)點(diǎn)的最近公共祖先在該樹的右子樹當(dāng)中 return lowestCommonAncestor(root->right, p, q); else //p、q結(jié)點(diǎn)的值一個(gè)比根小一個(gè)比根大,說明根就是這兩個(gè)結(jié)點(diǎn)的最近公共祖先 return root; } };
普通二叉樹
代碼如下:
//普通二叉樹 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; class Solution { public: bool Find(TreeNode* root, TreeNode* x) { if (root == nullptr) //空樹,查找失敗 return false; if (root == x) //查找成功 return true; return Find(root->left, x) || Find(root->right, x); //在左子樹找到了或是右子樹找到了,都說明該結(jié)點(diǎn)在該樹當(dāng)中 } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if (p == root || q == root) //p、q結(jié)點(diǎn)中某一個(gè)結(jié)點(diǎn)為根結(jié)點(diǎn),則根結(jié)點(diǎn)就是這兩個(gè)結(jié)點(diǎn)的最近公共祖先 return root; //判斷p、q結(jié)點(diǎn)是否在左右子樹 bool IspInLeft, IspInRight, IsqInLeft, IsqInRight; IspInLeft = Find(root->left, p); IspInRight = !IspInLeft; IsqInLeft = Find(root->left, q); IsqInRight = !IsqInLeft; if (IspInLeft&&IsqInLeft) //p、q結(jié)點(diǎn)都在左子樹,說明這兩個(gè)結(jié)點(diǎn)的最近公共祖先也在左子樹當(dāng)中 return lowestCommonAncestor(root->left, p, q); else if (IspInRight&&IsqInRight) //p、q結(jié)點(diǎn)都在右子樹,說明這兩個(gè)結(jié)點(diǎn)的最近公共祖先也在右子樹當(dāng)中 return lowestCommonAncestor(root->right, p, q); else //p、q結(jié)點(diǎn)一個(gè)在左子樹一個(gè)在右子樹,說明根就是這兩個(gè)結(jié)點(diǎn)的最近公共祖先 return root; } };
看著似乎不太好理解,來看看下面的動圖演示:
代碼如下:
//普通二叉樹 struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; class Solution { public: bool FindPath(TreeNode* root, TreeNode* x, stack<TreeNode*>& path) { if (root == nullptr) return false; path.push(root); //該結(jié)點(diǎn)可能是路徑當(dāng)中的結(jié)點(diǎn),先入棧 if (root == x) //該結(jié)點(diǎn)是最終結(jié)點(diǎn),查找結(jié)束 return true; if (FindPath(root->left, x, path)) //在該結(jié)點(diǎn)的左子樹找到了最終結(jié)點(diǎn),查找結(jié)束 return true; if (FindPath(root->right, x, path)) //在該結(jié)點(diǎn)的右子樹找到了最終結(jié)點(diǎn),查找結(jié)束 return true; path.pop(); //在該結(jié)點(diǎn)的左右子樹均沒有找到最終結(jié)點(diǎn),該結(jié)點(diǎn)不可能是路徑當(dāng)中的結(jié)點(diǎn),該結(jié)點(diǎn)出棧 return false; //在該結(jié)點(diǎn)處查找失敗 } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { stack<TreeNode*> pPath, qPath; FindPath(root, p, pPath); //將從根到p結(jié)點(diǎn)的路徑存放到pPath當(dāng)中 FindPath(root, q, qPath); //將從根到q結(jié)點(diǎn)的路徑存放到qPath當(dāng)中 //longpath和shortpath分別標(biāo)記長路徑和短路徑 stack<TreeNode*>* longPath = &pPath, *shortPath = &qPath; if (pPath.size() < qPath.size()) { longPath = &qPath; shortPath = &pPath; } //讓longPath先彈出差值個(gè)數(shù)據(jù) int count = longPath->size() - shortPath->size(); while (count--) { longPath->pop(); } //longPath和shortPath一起彈數(shù)據(jù),直到兩個(gè)棧頂?shù)慕Y(jié)點(diǎn)相同 while (longPath->top() != shortPath->top()) { longPath->pop(); shortPath->pop(); } return longPath->top(); //返回這個(gè)相同的結(jié)點(diǎn),即最近公共祖先 } };
到此這篇關(guān)于漫畫講解C語言中最近公共祖先的三種類型的文章就介紹到這了,更多相關(guān)C語言 公共祖先內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:
相關(guān)文章
C++構(gòu)造析構(gòu)賦值運(yùn)算函數(shù)應(yīng)用詳解
構(gòu)造函數(shù)主要作用在于創(chuàng)建對象時(shí)為對象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動調(diào)用,無須手動調(diào)用;析構(gòu)函數(shù)主要作用在于對象銷毀前系統(tǒng)自動調(diào)用,執(zhí)行一 些清理工作2022-09-09C語言中結(jié)構(gòu)體和共用體實(shí)例教程
這篇文章主要給大家介紹了關(guān)于C語言中結(jié)構(gòu)體和共用體的相關(guān)資料,結(jié)構(gòu)體是一種自定義的復(fù)合數(shù)據(jù)類型,共用體也叫聯(lián)合體,使幾個(gè)不同類型的變量共占一段內(nèi)存(相互覆蓋),需要的朋友可以參考下2021-06-06OpenCV實(shí)現(xiàn)輪廓的發(fā)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了OpenCV如何實(shí)現(xiàn)輪廓的發(fā)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05