根結點到所有葉子結點的路徑(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); } }

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM