算法——樹


樹:

定義:

樹是n個節點的有限集。n=0時稱為空樹。在任意一顆非空樹中:(1)有且僅有一個特定的稱為根(Root)的結點,(2)當n>1時,其余結點可分為m(m>0)個互不相交的有限集T1、T2、T3、……Tm,其中每一個集合本身又是一顆樹,並稱為根的子樹,如下圖

 

 

 

概念:

  • 樹的結點包含一個數據元素及若干指向其子樹的分支。結點擁有的子樹數稱為結點的度(Degree)。度為0的結點稱為葉結點(Leaf) 或終端結點;度不為0的結點稱為非終端結點或分支結點。除根結點之外,分支結點也稱為內部結點。樹的度是樹內各結點的度的最大值。因為這棵樹結點的度的最大值是結點D的度為3,所以樹的度也為3,如下圖:

 

 

  •  結點的子樹的根稱為該結點的孩子,相應的,該結點稱為孩子的雙親。同一個雙親的孩子之間互稱兄弟,如下圖:

 

 

  • 結點的層次從根開始,根為第一層,根的孩子為第二層。雙親在同一層的結點互為堂兄弟,樹中結點的最大層次稱為樹的深度或者高度,如下圖:

 

 

 

樹的父節點表示法:

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 
  5 /**
  6  *   樹的父節點表示法
  7  * @author wydream
  8  *
  9  */
 10 
 11 public class TreeParent<E> {
 12     
 13     //定義一個樹類
 14     public static class Node<T>{
 15         T data;//保存數據
 16         int parent;//保存父節點的位置
 17         public Node(){
 18             
 19         }
 20         
 21         public Node(T data) {
 22             this.data=data;
 23         }
 24         
 25         //指定根節點
 26         public Node(T data,int parent) {
 27             this.data=data;
 28             this.parent=parent;
 29         }
 30         
 31         public String toString() {
 32             return "TreeParent$Node[data=" + data + ", parent=" + parent + "]";
 33         }
 34     }
 35     
 36     private final int DEFAULT_TREE_SIZE=100;//樹的默認大小
 37     private int treeSize=0;//樹的實際大小
 38     //使用一個node數組來記錄該樹里的所有節點
 39     private Node<E>[] nodes;
 40     //記錄樹的節點數
 41     private int nodeNums;
 42     
 43     //以指定節點創建樹
 44     public TreeParent(E data) {
 45         treeSize=DEFAULT_TREE_SIZE;
 46         nodes=new Node[treeSize];
 47         nodes[0]=new Node<E>(data,-1);
 48         nodeNums++;
 49     }
 50     
 51     //以指定根節點、指定treeSize創建樹
 52     public TreeParent(E data,int treeSize){
 53         this.treeSize=treeSize;
 54         nodes=new Node[treeSize];
 55         nodes[0]=new Node<E>(data,-1);
 56         nodeNums++;
 57     }
 58     
 59     //為指定節點添加子節點
 60     public void addNode(E data,Node<E> parent) {
 61         for(int i=0;i<treeSize;i++) {
 62             // 找到數組中第一個為null的元素,該元素保存新節點
 63             if(nodes[i]==null) {
 64                 nodes[i]=new Node<E>(data,pos(parent));
 65                 nodeNums++;
 66                 return;
 67             }
 68             // 創建新節點,並用指定的數組元素保存它
 69         }
 70         throw new RuntimeException("該樹已滿");
 71     }
 72     
 73     // 判斷樹是否為空
 74     public boolean isEmpty() {
 75         return nodes[0]==null;
 76     }
 77     
 78     // 返回根節點
 79     public Node<E> root() {
 80         return nodes[0];
 81     }
 82     
 83     // 返回指定節點(非根結點)的父節點
 84     public Node<E> parent(Node<E> node) {
 85         return nodes[node.parent];
 86     }
 87     
 88     // 返回指定節點(非葉子節點)的所有子節點
 89     public List<Node<E>> children(Node<E> parent){
 90         List<Node<E>> list=new ArrayList<Node<E>>();
 91         for(int i=0;i<treeSize;i++) {
 92             // 如果當前節點的父節點的位置等於parent節點的位置
 93             if(nodes[i]!=null&&nodes[i].parent==pos(parent)) {
 94                 list.add(nodes[i]);
 95             }
 96         }
 97         return list;
 98     }
 99     
100     // 返回該樹的深度
101     public int deep() {
102         //用於記錄節點的最大深度
103         int max=0;
104         for(int i=0;i<treeSize&&nodes[i]!=null;i++) {
105             //初始化本節點的深度
106             int def=1;
107             //m 記錄當前節點的父節點的位置
108             int m=nodes[i].parent;
109             //如果其父節點存在
110             while(m!=-1&&nodes[m]!=null) {
111                 //向上繼續搜索父節點
112                 m=nodes[m].parent;
113                 def++;
114             }
115             if(max<def) {
116                 max=def;
117             }
118         }
119         return max;
120     }
121     
122     //返回包含指定值的節點
123     public int pos(Node<E> node) {
124         for(int i=0;i<treeSize;i++) {
125             //找到指定節點
126             if(nodes[i]==node) {
127                 return i;
128             }
129         }
130         return -1;
131     }
132     
133     
134     //測試
135     public static void main(String[] args) {
136         TreeParent<String> tp=new TreeParent<String>("root");
137         TreeParent.Node root=tp.root();
138         System.out.println(root);
139         tp.addNode("節點1", root);
140         System.out.println("此樹的深度"+tp.deep());
141         tp.addNode("節點2",root);
142         //獲取根節點的所有子節點
143         List<TreeParent.Node<String>> nodes=tp.children(root);
144         System.out.println("根節點的第一個子節點為:"+nodes.get(0));
145         // 為根節點的第一個子節點新增一個子節點
146         tp.addNode("節點3", nodes.get(0));
147         System.out.println("此樹的深度:" + tp.deep());
148         
149     }
150 }

 

程序運行結果:

TreeParent$Node[data=root, parent=-1]
此樹的深度2
根節點的第一個子節點為:TreeParent$Node[data=節點1, parent=0]
此樹的深度:3

  

樹的子節點表示法:

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 /**
  5  *   樹的子節點表示法
  6  * @author wydream
  7  *
  8  */
  9 
 10 
 11 public class TreeChild<E> {
 12 
 13     private static class SonNode{
 14         //記錄當前節點的位置
 15         private int pos;
 16         private SonNode next;
 17         
 18         public SonNode(int pos,SonNode next) {
 19             this.pos=pos;
 20             this.next=next;
 21         }
 22         
 23     }
 24     
 25     public static class Node<T>{
 26         T data;
 27         SonNode first;//記錄第一個子節點
 28         
 29         public Node(T data) {
 30             this.data=data;
 31             this.first=null;
 32         }
 33         
 34         public String toString() {
 35             if (first != null) {
 36                 return "TreeChild$Node[data=" + data + ", first=" + first.pos + "]";
 37             } else {
 38                 return "TreeChild$Node[data=" + data + ", first=-1]";
 39             }
 40         }
 41     }
 42     
 43     private final int DEFAULT_TREE_SIZE = 100;
 44     private int treeSize=0;
 45     
 46     // 使用一個Node[]數組來記錄該樹里的所有節點
 47     private Node<E>[] nodes;
 48     
 49     //記錄節點數
 50     private int nodeNums;
 51     
 52     // 以指定根節點創建樹    
 53     public TreeChild(E data) {
 54         treeSize=DEFAULT_TREE_SIZE;
 55         nodes=new Node[treeSize];
 56         nodes[0]=new Node<E>(data);
 57         nodeNums++;
 58     }
 59     
 60     // 以指定根節點、指定treeSize創建樹
 61     public TreeChild(E data,int treeSize) {
 62         this.treeSize=treeSize;
 63         nodes=new Node[treeSize];
 64         nodes[0]=new Node<E>(data);
 65         nodeNums++;
 66     }
 67     
 68     // 為指定節點添加子節點    
 69     public void addNode(E data,Node parent) {
 70         for(int i=0;i<treeSize;i++) {
 71             // 找到數組中第一個為null的元素,該元素保存新節點
 72             if(nodes[i]==null) {
 73                 // 創建新節點,並用指定數組元素保存它
 74                 nodes[i]=new Node(data);
 75                 if(parent.first==null) {
 76                     parent.first=new SonNode(i, null);
 77                 }else {
 78                     SonNode next=parent.first;
 79                     while(next.next!=null) {
 80                         next=next.next;
 81                     }
 82                     next.next = new SonNode(i, null);
 83                 }
 84                 nodeNums++;
 85                 return;
 86             }
 87         }
 88         throw new RuntimeException("該樹已滿,無法添加節點");
 89     }
 90     
 91     //判斷樹是否為空
 92     public boolean isEmpty() {
 93         return nodes[0]==null;
 94     }
 95     
 96     //返回根節點
 97     public Node<E> root(){
 98         return nodes[0];
 99     }
100     
101     //返回指定節點的所有子節點
102     public List<Node<E>> children(Node<E> parent){
103         List<Node<E>> list=new ArrayList<Node<E>>();
104         // 獲取parent節點的第一個子節點
105         SonNode next=parent.first;
106         // 沿着孩子鏈不斷搜索下一個孩子節點
107         while(next!=null) {
108             list.add(nodes[next.pos]);
109             next=next.next;
110         }
111         return list;
112     }
113     
114     // 返回指定節點(非葉子節點)的第index個子節點
115     public Node<E> child(Node parent,int index){
116         // 獲取parent節點的第一個子節點
117         SonNode next=parent.first;
118         // 沿着孩子鏈不斷搜索下一個孩子節點
119         for(int i=0;next!=null;i++) {
120             if(index==i) {
121                 return nodes[next.pos];
122             }
123             next=next.next;
124         }
125         return null;
126     }
127     
128     // 返回該樹的深度
129     public int deep() {
130         // 獲取該樹的深度
131         return deep(root());
132     }
133     
134     // 這是一個遞歸方法:每棵子樹的深度為其所有子樹的最大深度 + 1
135     public int deep(Node node) {
136         if(node.first==null) {
137             return 1;
138         }else {
139             // 記錄其所有子樹的最大深度
140             int max=0;
141             SonNode next=node.first;
142             // 沿着孩子鏈不斷搜索下一個孩子節點
143             while(next!=null) {
144                 // 獲取以其子節點為根的子樹的深度
145                 int tmp=deep(nodes[next.pos]);
146                 if(tmp>max) {
147                     max=tmp;
148                 }
149                 next=next.next;
150             }
151             // 最后,返回其所有子樹的最大深度 + 1
152             return max + 1;
153         }
154     }
155     
156     
157     // 返回包含指定值得節點
158     public int pos(Node node) {
159         for (int i = 0; i < treeSize; i++) {
160             // 找到指定節點
161             if (nodes[i] == node) {
162                 return i;
163             }
164         }
165         return -1;
166     }
167     
168     //測試
169     public static void main(String[] args) {
170 
171         TreeChild<String> tp = new TreeChild<String>("root");
172         TreeChild.Node root = tp.root();
173         System.out.println(root);
174         tp.addNode("節點1", root);
175         tp.addNode("節點2", root);
176         tp.addNode("節點3", root);
177         System.out.println("添加子節點后的根結點:" + root);
178         System.out.println("此樹的深度:" + tp.deep());
179         // 獲取根節點的所有子節點
180         List<TreeChild.Node<String>> nodes = tp.children(root);
181         System.out.println("根節點的第一個子節點:" + nodes.get(0));
182         // 為根節點的第一個子節點新增一個子節點
183         tp.addNode("節點4", nodes.get(0));
184         System.out.println("此樹第一個子節點:" + nodes.get(0));
185         System.out.println("此樹的深度:" + tp.deep());
186 
187     }
188 
189 
190     
191     
192 }

 

程序運行結果:

TreeChild$Node[data=root, first=-1]
添加子節點后的根結點:TreeChild$Node[data=root, first=1]
此樹的深度:2
根節點的第一個子節點:TreeChild$Node[data=節點1, first=-1]
此樹第一個子節點:TreeChild$Node[data=節點1, first=4]
此樹的深度:3

 


免責聲明!

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



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