我々は、データ型リニアアレイとリンクリストの構造を研究する前に、今日見た非線形構造のデータ型ツリー(多くの1つ)。ツリーは、多くの場合、その上、このようなコンピュータシステムおよびファイル構造の私達の紙カタログ、部門のスタッフの構造図として、私たちの日常生活の中で使用され、そして。階層構造を有する一般的な線形構造に比べて、それがデータ構造の線形関数よりも強力である、よりなります。そこで、この記事の著者は、フリーツリーを達成するために、配列を使用する方法について説明します。
関連する定義をオンラインで収集を開始し、木の特性を属性:
説明
図ツリーは、あるデータ構造の階層関係を有する有限のノードからなるN(N> = 1)であるセット。それは上向き、下向きや葉のルートであることを意味逆さまの木のように見えるので、私たちは「木」と呼んでいます。それは次の機能があります。
各ノードは、ゼロ個以上の子ノードを有しており、親ノードはルートノードと呼ばれていない、各非ルートノードは、唯一の親ノードを有し、ルートまた、各子ノードをこれは、複数のサブツリーばらばらに分けることができます
定義
ツリー N(N> = 0)を含む(木)は、前記ノードの有限集合です。
(1)各要素ノードは、(ノード)と呼ばれます。
(2)特定のノードは、ルートノードまたはルート(ルート)と呼ばれます。
(3)ルートノード以外の残りのデータ要素をm(m≥0)互いに素なセットT1、T2に分割され、... TM-1、それぞれは、Tiを設定し、前記(1 <= l <= M )自体は、ツリーが元のサブツリー(サブツリー)と呼ばれる、木です。
ツリーが定義することができます。rootと木がいくつかの部分で構成さサブツリーです。ツリーが設定され、セット内に定義された関係で構成されています。コレクションと呼ばれるツリーノードの要素は、親子関係の定義は、関係と呼ばれています。ツリーのノード間の親子関係は、階層を確立します。この階層で特別な位置を有するノードがあり、このノードは、そうでない場合は、ルートとして知られ、ツリーのルートノードと呼ばれています。
私たちは、木に体を得ることができ、再帰的に次のように定義します:
シングルノードがルートノード自体である木です。
.. T1、T2を設定し、Tkがツリー、N1であるのルート、N2、...、NKです。新しいノードN1、N2、...、nkは父親としてのnで、新しい木が得られ、nはツリーの新しいルートノードです。私たちは、N1、N2、...、NKは、子ノードnのノードである兄弟ノードの集合であると呼んでいます。我々はまた、T1、T2は、...、Tkはサブツリーのノードnであることを特徴とします。
空のセットが空の木と呼ばれる木、です。空のツリーノードません。
関連用語
ノード:ノードを含むノード番号サブツリーが参照されます。
端末ノードまたはリーフノード:次数0のノードは、リーフノードと呼ばれます。
非終端ノードまたはブランチノード:ノードの次数は0ではありません。
親または親ノード:子ノードを備えたノードの場合、このノードはその子ノードの親ノードと呼ばれます。
子供や子供:ノードのと呼ばれる子ノードを含むサブツリーのルートノード。
兄弟ノード:同じ親ノードを有するノードが相互兄弟ノードと呼ばれます。
木の:木、木の最大次数は、ノードと呼ばれます。
レベルのノード:開始の定義からルートから、ように第一層、第二層のルートの子との根;
木の高さまたは深さ:ツリー内の最大レベルのノード。
いとこノード:互いにいとこの同じ層における親ノード。
祖先ノード:ノードに至るルートから分岐上のすべてのノード。
息子:子孫ノードのいずれかで言及ノードをルートとするサブツリー内のノード。
森森の木と呼ばれるM組(M> = 0)ばらばら木。
以降に導入上記の用語の多くを読んだ後、あなたの心にあなたが一般的なモデルを持っている必要がありますが、それは明らかに十分ではないかもしれない、のは私たちがそれを理解するためにマップを使用してみましょう。
ツリー構造の概略図
この絵は、木のフリーフォームを言う我々は、ツリーの下部にある木に住んでいるように、各構造が近くなるように、この絵は、180°回転置けばツリーのルートで、トランクは、その後、何のクロスアップはありません木の枝を成長させるための木の幹との関係で、枝はトランクアウト部分から独立している、その後、さらに上の樹木の葉です。
今日、我々は、(図1号は、ルート・ノードである)ツリーにも記述するためにこれらの用語を使用することができますが、私たちはこの木を知る、それはその根の上逆さまであることを学びますツリー構造は2,3,4は、サブのルートノードである(ルートノード0-Nの下にあってもよい、(NOルートをすることができ、ツリーのルートは、我々が呼ぶ空の木でない)最大1つのルートを持つことができノード)、および各ノードの下に子ノードができ0を-N ...それはすでにトップレベルであるので、我々は、葉(5,6,7,8-がリーフノードに属している)を呼び出していない子ノード。さらに、木構造の根、葉、または残りのノードを除いて、唯一の親ノードを有しています。
ツリー構造の各ノードは、ルートノードとの間に一つだけのユニークなパスを持っています。
新しいノード操作を追加する:あなたは、その親がツリー構造に新しいノードを追加しているユーザーを指定する必要があります。
新しいノードの概略図を追加
親ノードを指定し、新たに追加されたノードとして図レッドNo. 9は、2であり、これもノード9内のノードを添加した後、以下第2号。
あなたはノードが唯一それ自体を削除するには、リーフノードで削除すると、ノードがルートノードは、削除ツリー全体を削除している場合、それ以外の場合は、ノードとそのすべての子孫ノードを削除します:ノード操作を削除します。
回路図、削除ノード
図3は、ノードとその子番号3番6及び7が削除され、ノードが削除されます。
トラバーサル操作:ロードマップは、ルートにすべてのノードを見つけると、すべてのノードを検索します。
ノードトラバーサル概略図
実現
ツリー構造の関連する特性の理論的研究の後、私たちは今、それを実装するためのコードを使用しています。
ツリーを達成するための2つの方法があります。
- 配列
- リスト
今日、この記事では、自由ツリーを達成するために配列を使用する方法について説明します。
まず需要を整理:
- 私たちは、ツリーを作成する必要があります
- ツリーに新しいノードを追加するために実装することができます
- ツリー内のノードとその子を削除達成することができます
- あなたは木の深さを返すことができます
- あなたは、ツリー内のすべてのノードをたどることができます
- あなたは、ノードの親を返すことができます。
- ノードは、以下のすべての子ノードを返すことができます
一時的に、我々は最初の7つの要件を終了します。
いくつかの単語の男は、コードに言いました:
package dataStructure;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Viking on 2019/4/22
*/
public class MyArrayTree<E> {
private static final int DEFAULT_SIZE=20;
private int size;
private Node<E>[] nodes;
private int nodeNum;
@SuppressWarnings("unchecked")
public MyArrayTree(E data){
size = DEFAULT_SIZE;
nodes = new Node[size];
nodes[0] = new Node<>(data,-1);
nodeNum++;
}
@SuppressWarnings("unchecked")
public MyArrayTree(E data,int capacity){
size = capacity;
nodes = new Node[size];
nodes[0] = new Node<>(data,-1);
nodeNum++;
}
/**
* 添加新节点
*/
public Node<E> addNode(E data,Node parent){
for (int i=0;i<size;i++){
if (null==nodes[i]) {
nodes[i] = new Node<>(data, pos(parent));
nodeNum++;
return nodes[i];
}
}
throw new RuntimeException("该树已满,无法添加新节点");
}
/**
* 删除节点及其所有子节点
*/
public void remove(Node node){
while (children(node).size()>0){
for (Node child : children(node)){
remove(child);
}
}
for (int i=0;i<nodes.length;i++){
if (nodes[i]!=null&&nodes[i]==node){
nodes[i]=null;
size--;
}
}
}
public List<String> list(){
return list(getRoot());
}
public List<String> list(Node root){
return list(new ArrayList<>(),"",root);
}
/**
* 遍历
*/
private List<String> list(List<String>list,String index,Node root){
List<Node<E>> children = children(root);
list.add(index+root.data);
while (children.size()>0){
for (Node node : children){
list = list(list,index+"\t",node);
}
children.clear();
}
return list;
}
public boolean isEmpty(){
return nodeNum==0;
}
public Node<E> getRoot(){
return nodes[0];
}
public Node<E> getParent(Node node){
return nodes[node.parent];
}
/**
* 列出所有的子节点
*/
public List<Node<E>> children(Node node){
List<Node<E>> list = new ArrayList<>();
for (int i=0;i<size;i++){
if (null!=nodes[i]&&nodes[i].parent==pos(node))
list.add(nodes[i]);
}
return list;
}
/**
* 树的深度
*/
public int deep(){
int max = 0;
for (int i = 0;i<size&&nodes[i]!=null;i++){
int deep = 1;
int p = nodes[i].parent;
while(-1!=p&&nodes[p]!=null){
p = nodes[p].parent;
deep++;
}
if (deep>max) max = deep;
}
return max;
}
private int pos(Node node){
for (int i=0;i<size;i++){
if (nodes[i]==node) return i;
}
return -1;
}
public static class Node<T>{
T data;
int parent;
public Node(T data ,int parent){
this.data = data;
this.parent = parent;
}
}
}
テストクラスを書きます:
import dataStructure.MyArrayTree;
import java.util.List;
/**
* Created by Viking on 2019/4/22
* 测试自定义实现的树形结构
*/
public class TestMyTree {
public static void main(String[] args) {
MyArrayTree<String> tree = new MyArrayTree<>("root");
System.out.println("Before add node:"+tree.deep());
MyArrayTree.Node<String> node = tree.addNode("node", tree.getRoot());
System.out.println("After add node:"+tree.deep());
MyArrayTree.Node<String> root = tree.getRoot();
List<MyArrayTree.Node<String>> children = tree.children(root);
tree.addNode("Children",children.get(0));
System.out.println("After children node:"+tree.deep());
tree.remove(tree.children(children.get(0)).get(0));
System.out.println("After remove node:"+tree.deep());
MyArrayTree.Node<String> left = tree.addNode("left", root);
MyArrayTree.Node<String> right = tree.addNode("right", root);
tree.addNode("grandson1OfLeft",left);
tree.addNode("grandson2OfLeft",left);
tree.addNode("grandson1OfRight",right);
tree.addNode("grandson2OfRight",right);
MyArrayTree.Node<String> childOfNode = tree.addNode("childOfNode", node);
tree.addNode("childOfNodes'child",childOfNode);
List<String> list = tree.list();
for (String data : list){
System.out.println(data);
}
System.out.println("----------------------------------");
List<String> list1 = tree.list(node);
for (String data : list1){
System.out.println(data);
}
}
}
テスト結果:
Before add node:1
After add node:2
After children node:3
After remove node:2
root
node
childOfNode
childOfNodes'child
left
grandson1OfLeft
grandson2OfLeft
right
grandson1OfRight
grandson2OfRight
----------------------------------
node
childOfNode
childOfNodes'child