二分木の演習 (詳細な再帰展開図)

序章

先ほど、二分木の基礎知識を紹介し、二分木の表現には逐次構造と連鎖構造の2つの構造があることを学びました。つまり、シーケンシャル リストまたはリンク リストを使用してバイナリ ツリーを表現します。
バイナリ ツリーの詳細な説明を参照してください。

前回の記事では、バイナリ ツリー (つまり、ヒープ) への逐次アクセスとそのインターフェイスの実装について学びました。
ヒープとインターフェイスの実装については、こちらをご覧ください。

この記事では二分木の連鎖アクセスを紹介しますが、連結リストのノードが二分木のノードに自由にアクセスすることは難しいため、連鎖二分木を使って追加することは実際には意味がありません。 、削除、確認、変更します。この記事では、バイナリ ツリー チェーン構造に関するいくつかのトピックを紹介します。単一値バイナリ ツリー、バイナリ ツリーの最大深さ、反転バイナリ ツリー、同一ツリーです。

連鎖二分木のノード構造により、優れた再帰特性を備えています。この記事では、次のことを説明するために再帰展開図を詳細に描きます。

typedef int BTDataType;
struct BinaryTreeNode
{
    
    
    struct BinTreeNode* _pLeft; // 指向当前节点左孩子
    struct BinTreeNode* _pRight; // 指向当前节点右孩子
    BTDataType _data; // 当前节点值
}

単一値二分木

単一値二分木 OJ リンク

トピックの説明とアイデア

ここに画像の説明を挿入
バイナリツリー内の値がすべて等しいかどうかを判断し、等しい場合は true を返し、そうでない場合は false を返す関数を実装する必要があります。

再帰することができます:
各再帰は、このノードとその左右の子ノードの値が等しいかどうかを判断し、等しい場合は次のレベルに true を返し、そうでない場合は false を返します。このノードが NULL の場合、このノードの
再帰行が終了し、行が上に上がる レベルは true を返します。
このノードは判断され、true の場合は下方向への再帰を継続し、それ以外の場合は直接 false を返します。

上位に戻る場合は、このノードの左右の子ノードがそれぞれtrueを返した場合のみtrueとなるので、その左右の子ノードが返した値の論理積をとった結果を返します。

達成

まずルートが NULL かどうかを判断し、NULL の場合は直接 true を返し、
このノードの値が左右の子の値と等しくない場合は直接 false を返し、
等しくなったらその左右の子を使用します。ノードをルート ノード root として、それぞれ再帰的に実行すると、返される値の論理 AND の結果が返されます。

bool isUnivalTree(struct TreeNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		return true;
	}
	if ((root->left && root->left->val != root->val)||(root->right && root->right->val != root->val))
	{
    
    
		return false;
	}
	else
	{
    
    
		return isUnivalTree(root->left) && isUnivalTree(root->right);
	}
}

再帰展開グラフ(関数コードが少し長いため、グラフ描画時に関数名と戻り値のみを記述します):
ここに画像の説明を挿入

バイナリツリーの最大深さ

二分木の最大深さOJリンク

トピックの説明とアイデア

ここに画像の説明を挿入
バイナリ ツリーの最大の深さを見つける関数を実装する必要があります。


ノードの左右のサブツリーの深さを再帰的に計算し、次に
左右のサブツリーの深さを比較し、大きい方の値 + 1 がノードの深さとなり、この値を上位に返します。レベル。

達成

この問題の実現は比較的簡単です。

まずノードが NULL かどうかを判断し、NULL の場合は直接 0 を返し、
次に左右のサブツリーの深さをそれぞれ計算して保存し、
最後に大きい方の左右のサブツリー + 1 の値を返します。

左右のサブツリーの深さを計算した後、結果を保存する必要があることに注意してください。保存しないと、効率が重大な影響を受けます。

int maxDepth(struct TreeNode* root) 
{
    
    
	if (root == NULL)
	{
    
    
		return 0;
	}
	int lefthigh = maxDepth(root->left);
	int righthigh = maxDepth(root->right);

	return lefthigh > righthigh ? lefthigh + 1 : righthigh + 1;
}

再帰展開図(NULL判定部分を省略):
ここに画像の説明を挿入

二分木を反転する

バイナリ ツリー OJ リンクを反転する

トピックの説明とアイデア

ここに画像の説明を挿入
二分木の左右のノードの反転を実現する関数を実装する必要があります。

バイナリ ツリーの各ノードには、このノードの値と 2 つの子ノードのポインタが含まれていることがわかっているため、各ノードの左右の子ノードのポインタを再帰的に交換するだけで済みます。

達成

まずこのノードが NULL かどうかを判断し、空の場合は NULL を返し、
次に 2 つの子ノードのポインタを交換し、
次に左右の子ノードをパラメータとして再帰し、
最後にこのノードのポインタを上位レベルに返します。

struct TreeNode* invertTree(struct TreeNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		return NULL;
	}
	struct TreNode* temp = root->left;
	root->left = root->right;
	root->right = temp;

	invertTree(root->left);
	invertTree(root->right);
	return root;
}

再帰的展開図:
ここに画像の説明を挿入

同じ木

同木OJリンク

トピックの説明とアイデア

ここに画像の説明を挿入
2 つのバイナリ ツリーが同じかどうかを判断し、等しい場合は true を返し、そうでない場合は false を返す関数を実装する必要があります。

各ノード自体がその左右の子ノードと等しいかどうかを再帰的に判断できます。
判断するときは、ノードの値が等しいかどうかのみ判断できます。
ノードが等しい場合は、下方向に再帰し、左右の子ノードを返します。値の論理積の結果。

達成

最初に p と q が空かどうかを判断し、両方が空の場合は true を返し、
すべてが空ではなくいずれか 1 つが空である場合は、等しくないことを意味し、false を返します。その後、
値が正しいかどうかを判断します。このノードの が等しい場合、等しくない場合は false を返し、
等しい場合は、2 つのツリーの左側と右側のノードをそれぞれ再帰し、それらの戻り値の論理 AND の結果を返します。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    
    
	if (p == NULL && q == NULL)
	{
    
    
		return true;
	}
	else if (p == NULL || q == NULL)
	{
    
    
		return false;
	}
	if(p->val!=q->val)
	{
    
    
		return false;
	}
	else
	{
    
    
		return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
	}
}

再帰展開図(判定部分省略):
ここに画像の説明を挿入

要約する

この時点で、連鎖バイナリ ツリーに関する OJ 演習がいくつか紹介されています。

この部分を明確に紹介していない、またはこの部分に問題があると思われる場合は、コメント欄に指摘してください。

この記事が少しでもお役に立てましたら、ワンクリックでつながれば幸いです

皆さんと一緒に進歩していきたいと思っています

おすすめ

転載: blog.csdn.net/weixin_73450183/article/details/130027320