木の概念と特徴
1木の概念
- ツリーはリンクリストに似た線形構造ですが、典型的な非線形構造でもあります。ツリーには強い階層があります。線形構造と比較すると、ツリーは時間の複雑さが低く、効率が高く、読者は連絡できます。人生で見られる木。
2ツリー用語
- 最初に次のようにツリーの画像を見て、図の矢印と関連する用語を削除します。ツリーは非線形階層です。
ツリーの関連用語は次のとおりです。
- ルートノード:親ノードのないノード、上のノードA。
- 兄弟ノード:同じ親ノードを持つ子ノード。たとえば、FとGは兄弟ノードです。
- リーフ・ノード ;
没有孩子节点的节点
例えばD、F、G、I、など ; J - 祖先と孫:ルートノードAからノードJへのパスがあり、そのパスにノードEが表示される場合、EはノードJの祖先ノードと呼ばれ、JはEの孫である; ABEHはJと見なすことができる祖先ノード
- ノードサイズ:ノードのサイズは、
拥护的孙节点个数
それ自体を含むノードを指します。たとえば、Eノードのサイズは4です。 - ノードの深さ:ノードへのルートノードを指します
路径长度
(例:(ABD)、2つのチェーンの深さ、つまり、Dノードは2)。 - ノードの高さ:最も深いノードまでのノードを指します
路径长度
。たとえば(E-H -J)、2つのチェーン、つまり、Eノードの高さは2です。 - ツリーのレベル:同じ深さのセットは、ツリーのレベルと呼ばれます(たとえば、BとC、たとえば、D、E、F、G)。
- ツリーの高さと深さ:ツリーの深さはすべてのノードの最大の深さを指し、ツリーの高さはすべてのノードの最大の高さを指します。
树的高度等于树的深度
3木の種類
-
バイナリツリー:ツリー内の各ノードに0、1、または2つのノードがある場合、そのツリーはバイナリツリーと呼ばれるため、空のツリーもバイナリツリーです。
-
厳密なバイナリツリー:ツリーの各ノードには、左または右の子があるか、子がありません。
- オブリークツリー:オブリークツリーの各ノードには子が1つだけあります。オブリークツリーの各ノードに左の子しかない場合は、左のオブリークツリーと呼ばれます。オブリークツリーの各ノードに右の子しかない場合は、右のオブリークツリーと呼ばれます。
- 完全な二分木:すべての親ノードには左右の子があり、すべてのリーフノードは同じレイヤーにあるため、この種のツリーは完全な二分木と呼ばれます
- 完全二分木:N個のノードを含むバイナリツリーの階層数で、つつ、左、右の第1、次いで子右の子の数に応じて子供を残した場合、ノードIの数とノードIの同じ数の深さの完全なバイナリツリーバイナリツリーの位置はまったく同じです。このバイナリツリーは完全なバイナリツリーと呼ばれます。したがって、完全なバイナリツリーは完全なバイナリツリーである必要があります。
2.4完全な二分木の性質
-
完全なフォークツリーのノード数:完全な二分木のレベルがkであると仮定すると、数学的帰納法と比例シーケンスの式によれば、2 ^ 0 + 2 ^ 1 +…+ 2 ^ k = 2 ^(k + 1)- 1;導出プロセスは次のとおりです。
-
完全二分木の葉ノードの数:完全二分木の構造によれば、k番目のレイヤーは葉ノードが配置されているレイヤーなので、葉ノードの数は2 ^ kです。
バイナリツリーの実装
二分木の構造
- バイナリツリーの構造によれば、各ノードは、左右のポインタに対応する左右の子を持つと想定でき、各ノードは値を格納できるため、オブジェクト指向プログラミングのアイデアによる抽象化の後クラスは以下の通り
/**
* <p>二叉树的结构 </p>
*/
public class TreeNode {
// 左孩子
private TreeNode leftNode;
// 右孩子
private TreeNode rightNode;
// 存储值
private Object value;
// 构造方法
TreeNode(Object value){
this.value = value;
}
// 省略 set get
}
- ここで、次の完全なバイナリツリーを実装する必要があります。
アイデアは次のとおりです。
- 最初にルートノードに1が格納され、次に左の子2と右の子3がそれぞれ格納されます。
- 次に、左の子ノードが親ノードとして使用され、左の子4と右の子5がそれぞれ格納されます。
- 最後に、右の子ノードは親ノードとして機能し、左の子6と右の子7をそれぞれ格納します。
- コードは次のように実装されます。
public static void main(String[] args) {
// 初始化树
TreeNode tree = initTree();
}
public static TreeNode initTree(){
// 创建7个节点
TreeNode treeNode1 = new TreeNode(1);
TreeNode treeNode2 = new TreeNode(2);
TreeNode treeNode3 = new TreeNode(3);
TreeNode treeNode4 = new TreeNode(4);
TreeNode treeNode5 = new TreeNode(5);
TreeNode treeNode6 = new TreeNode(6);
TreeNode treeNode7 = new TreeNode(7);
// 根据上面思路对节点进行组装
// 组装根节点
treeNode1.setLeftNode(treeNode2);
treeNode1.setRightNode(treeNode3);
// 组装左孩子
treeNode2.setLeftNode(treeNode4);
treeNode2.setRightNode(treeNode5);
// 组装右孩子
treeNode3.setLeftNode(treeNode6);
treeNode3.setRightNode(treeNode7);
return treeNode1;
}
二分木の探索と実現
- 二分木の探索は、前順探索、中位探索、およびその後の探索に分けられます。現在のノードをC(現在のノード)、左側のノードをL、右側のノードをRとすると、
前序遍历:C----->L------->R
中序遍历:L----->C------->R
后续遍历:R----->C------>L
予約注文トラバーサルの実装
アイデア:
- 最初に現在のノードにアクセスします。
- 2番目に左ノードにアクセスします。
- 最後に訪問したノード。
- 前の図に戻ると、プレオーダートラバーサルCLRは1、2、4、5、3、6、7です。
public static void main(String[] args) {
// 初始化树
TreeNode tree = initTree();
// 调用先序遍历
preOrderTree(tree);
}
/**
* <p> 先序遍历</p>
* @Param [rootNode]
* @Return void
*/
public static void preOrderTree(TreeNode rootNode){
if (rootNode!=null){
// 值
System.out.println(rootNode.getValue());
// 左孩子
preOrderTree(rootNode.getLeftNode());
// 右孩子
preOrderTree(rootNode.getRightNode());
}
}
- アウトプット
1
2
4
5
3
6
7
- プリオーダートラバーサルの実装は、時間の複雑さがO(n)の線形実装です。
順序トラバーサルの実装
アイデア:
- 最初に左側のノードにアクセスします
- 2番目に現在のノードにアクセスする
- 正しいノードを最後に訪問
- 前の図に戻ると、順次走査の結果は4、2、5、1、6、3、7になります。
public static void main(String[] args) {
// 初始化树
TreeNode tree = initTree();
// 调用中序遍历
middleOrderTree(tree);
}
/**
* <p> 中序遍历</p>
* @Param [rootNode]
* @Return void
*/
public static void middleOrderTree(TreeNode rootNode){
if (rootNode!=null){
// 左孩子
middleOrderTree(rootNode.getLeftNode());
// 值
System.out.println(rootNode.getValue());
// 右孩子
middleOrderTree(rootNode.getRightNode());
}
}
- アウトプット
4
2
5
1
6
3
7
- 中次走査の実装は、時間の複雑さがO(n)の線形実装です。
後続のトラバーサルの実装
アイデア:
- 最初に左側のノードにアクセスします
- 2番目に適切なノードにアクセスする
- 現在のノードを最後に訪問
- 前の図に戻ると、順次走査の結果は4、5、2、6、7、3、1になります。
public static void main(String[] args) {
// 初始化树
TreeNode tree = initTree();
// 调用后续遍历
postOrderTree(tree);
}
/**
* <p>后续遍历 </p>
* @Param [rootNode]
* @Return void
*/
public static void postOrderTree(TreeNode rootNode){
if (rootNode!=null){
// 左孩子
postOrderTree(rootNode.getLeftNode());
// 右孩子
postOrderTree(rootNode.getRightNode());
// 值
System.out.println(rootNode.getValue());
}
}
- アウトプット
4
5
2
6
7
3
1
- ポストオーダートラバーサルの実装は、時間の複雑さがO(n)の線形実装です。