根結點到所有葉子結點的路徑(java、C++)
阿新 • • 發佈:2020-08-16
java(針對樹的編碼),C++(針對二叉樹的編碼)
思路一:
採用深度優先遍歷(java Stack,C++ vector)的方式,每當遇到葉子節點,此刻棧裡面的內容就是該葉子節點對應的一條路徑
java
注意到達葉子節點過後,得到了這條路徑,需要把葉子節點立馬出棧,注意出棧程式碼寫的位置
可以寫在出棧位置1,或者寫在出棧位置2
參考:https://blog.csdn.net/leixingbang1989/article/details/40587405/
class node { private String text; private List<node>childList; } publicclass IteratorNodeTool { Map<String,List> pathMap=new HashMap();//記錄所有從根節點到葉子結點的路徑 private void print(List lst)//打印出路徑 { Iterator it=lst.iterator(); while(it.hasNext()) { node n=(node)it.next(); System.out.print(n.text+"-"); } System.out.println(); }public void iteratorNode(node n,Stack<node> pathstack) { pathstack.push(n);//入棧 List childlist=n.childList; if(childlist==null)//沒有孩子 說明是葉子結點 { List lst=new ArrayList(); Iterator stackIt=pathstack.iterator(); while(stackIt.hasNext()) { lst.add(stackIt.next()); } print(lst);//列印路徑 pathMap.put(n.getText(), lst);//儲存路徑資訊 return; }else { Iterator it=childlist.iterator(); while(it.hasNext()) { node child=(node)it.next(); iteratorNode(child,pathstack);//深度優先 進入遞迴 pathstack.pop();//回溯時候出棧,出棧位置1 } }
//pathstack.pop();//出棧位置2 } public static void main(String[] args) { Stack <node>pathstack=new Stack(); node n=node.getInitNode(); IteratorNodeTool tool=new IteratorNodeTool(); tool.iteratorNode(n, pathstack); } }
C++
參考:https://blog.csdn.net/zzIymt/article/details/50816059
void LeavesPath(TreeNode* root, vector<int> &path){//引用vector if (root == NULL) return; path.push_back(root->val); if (root->left == NULL&&root->right == NULL){ for (int i = 0; i < path.size(); i++){ cout << path[i] << " "; } cout << endl; } else { LeavesPath(root->left, path); LeavesPath(root->right, path); } path.pop_back();//關鍵 }
或者(出棧程式碼位置不同)
void LeavesPath(TreeNode* root, vector<int> &path){//引用vector if (root == NULL) return; path.push_back(root->val); if (root->left == NULL&&root->right == NULL){ for (int i = 0; i < path.size(); i++){ cout << path[i] << " "; } cout << endl; } else { LeavesPath(root->left, path); path.pop_back();//關鍵 LeavesPath(root->right, path); path.pop_back();//關鍵 } }
// 測試程式碼 vector<int> path; LeavesPath(&n0, path);//n0為自己建造的樹的根結點
思路二:陣列
少了思路一中的出棧操作,因為陣列在指定索引賦值可以直接覆蓋原有的值,並且用len記錄了當前節點的深度(根節點深度為0)
void LeavesPath2(TreeNode* root, int* path,int len){ if (root == NULL) return; path[len++] = root->val; if (root->left == NULL&&root->right == NULL){ for (int i = 0; i < len; i++){ cout << path[i] << " "; } cout << endl; } else { LeavesPath2(root->left, path, len); LeavesPath2(root->right, path, len); } }
//測試程式碼 int path2[20] = { 0 }; LeavesPath2(&n0, path2, 0); //n0為自己建造的樹的根結點
(引用)陣列+引用長度
注意這兒引數的len是一個引用,當遞迴的時候,其實操作的都是同一個物件。
而思路二中的len引數 定義為int len,是一個區域性變數
void LeavesPath3(TreeNode* root, int* &path, int& len){//int* &path替換成int*path也可以 if (root == NULL) return; path[len++] = root->val; if (root->left == NULL&&root->right == NULL){ for (int i = 0; i < len; i++){ cout << path[i] << " "; } cout << endl; } else { LeavesPath3(root->left, path, len); LeavesPath3(root->right, path, len); } --len;//這步操作與版本一中pop_back目的一樣。 }
//測試程式 int path2[20] = { 0 }; int len = 0; int *path3 = path2; LeavesPath3(&n0, path3, len);//n0為自己建造的樹的根結點