二叉樹,結構很簡單,只是比單鏈表複雜了那麼一丟丟而已。咱們先來看看它們結點上的差別:node
/* 單鏈表的結構 */ struct SingleList{ int element; struct SingleList *next; };
/* 二叉樹的結構 */ struct BinaryTree{ int element; struct BinaryTree *left; struct BinaryTree *right; };
根據以上兩個結構,咱們不難發現,單鏈表的結點只有一個指向下一結點的指針,而二叉樹中有兩個。也就是說單鏈表每一個結點只有一個子節點,而二叉樹有兩個子節點(其中一個可能爲NULL)。瞭解了這一點的區別,咱們就知道:基於二叉樹的算法比基於單鏈表的算法差別就是每次遍歷一個結點以後,須要遍歷兩個子節點,而單鏈表只須要遍歷一個子節點。git
這就引出了2種遍歷的方法:廣度優先遍歷(BFS)和深度優先遍歷(DFS)。github
對於單鏈表來講,BFS和DFS是同樣的,由於每一個節點只有一個子節點,每次遍歷下一個節點只有一種選擇;可是二叉樹每一個節點有兩個子節點,也就是說遍歷的順序既能夠遍歷它的子節點(不管左節點仍是右結點都是DFS),也能夠遍歷它的兄弟結點。若是是每次先遍歷子節點那麼就是DFS;每次先遍歷兄弟結點,就是BFS。算法
DFS採用棧結構,博主這裏用的是遞歸來實現棧,固然你們也能夠用stack來實現;BFS採用的是隊列queue。spa
void dfs(BinaryTree *root){ if(NULL == root) return ; dfs(root->left); dfs(root->right); }
void bfs(BinaryTree *root){ if(NULL == root) return ; queue<BinaryTree *> que; que.push(); while(!que.empty()){ BinaryTree *pNode = que.front(); que.pop();
if(pNode->left) que.push(pNode->left); if(pNode->right) que.push(pNode->right); } }
關於樹的一些算法中,DFS和BFS通常都適用,可是當涉及到根到葉的路徑這類問題時,最好仍是用DFS來實現。以下所示:指針
一、給一棵二叉樹和一個值Sum,求出全部從根到葉子的值等於Sum的全部路徑。code
思路:深度優先搜索(DFS),而後把從跟開始每次訪問一個結點就把該結點添加到一個vec的最後位置,並把sum減去當前借點的值後傳遞給下一個節點,當一個結點的左右孩子都爲NULL,而且值等於sum時,就說明該節點是葉子節點,而且從根結點到該節點的路徑和爲Sum,把vec,添加到res中;每次返回時,須要把vec中的最後一個值刪除,由於每一個節點有兩個子節點,從根節點到左孩子的葉子的路徑與到右孩子葉子的路徑是不一樣的,全部每次訪問完左孩子或者右孩子須要把孩子的值從vec中刪除。blog
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { private: vector<vector<int>> res; vector<int> vec; void _pathSum(TreeNode* root, int sum){ if(root == NULL) return ; vec.push_back(root->val); if(root->left == NULL && root->right == NULL && sum == root->val){ res.push_back(vec); return ; } _pathSum(root->left, sum-root->val); if(root->left) vec.pop_back(); _pathSum(root->right, sum-root->val); if(root->right) vec.pop_back(); } public: vector<vector<int>> pathSum(TreeNode* root, int sum) { if(NULL == root) return res; _pathSum(root, sum); return res; } };
二、轉化二叉樹遞歸
把二叉樹:隊列
4 / \ 2 7 / \ / \ 1 3 6 9
轉化成
4 / \ 7 2 / \ / \ 9 6 3 1
思路:這個既能夠用DFS也能夠用BFS,也就是遍歷每一個節點,而後將它們的左右孩子互換便可。這裏採用BFS來實現:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* invertTree(TreeNode* root) { if(NULL == root) return NULL; queue<TreeNode*> que; que.push(root); while(!que.empty()){ TreeNode* pChild = que.front(); que.pop(); TreeNode* pNode = pChild->left; pChild->left = pChild->right; pChild->right = pNode; if(pChild->left) que.push(pChild->left); if(pChild->right) que.push(pChild->right); } return root; } };
三、總結
只要掌握了DFS和BFS的思想,其它關於二叉樹的算法基本上都是相似的,必要的時候經過畫圖來讓本身感性認識一下也是極好的。
關於Leetcode上的題目代碼:https://github.com/whc2uestc/onlineJudge/tree/master/leetCode
版權全部,歡迎轉載,轉載請註明出處。