1. 程式人生 > 實用技巧 >根結點到所有葉子結點的路徑(java、C++)

根結點到所有葉子結點的路徑(java、C++)

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;
}

public
class 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為自己建造的樹的根結點