「データ構造の初歩的」一般的な二分木問題の解決策-再帰的記述

序文

通常の二分木の再帰的記述方法については、書くのは簡単ですが、理解するのが少し難しいので、プレオーダー、インオーダー、ポストオーダートラバーサルの基礎が必要です。この章の問題解決は、再帰的な拡張図を描くのではなく、思考とコードを提供するだけです。

1.この章の焦点

  1. 。単一値の二分木
  2. 2本の木が同じかどうかを確認します
  3. 対称二分木
  4. 別の木のサブツリー
  5. 二分木の構築とトラバーサル

2.単一値の二分木

bool isUnivalTree(struct TreeNode* root)

 再帰的なアイデア:ルートがNULLの場合、trueを返します。

左の子が存在する場合、左の子の値がルートノードの値と等しくない場合はfalseを返します。

同様に、右の子が存在する場合、右の子の値がルートノードの値と等しくない場合は、falseを返します。

次に、会う:

return isUnivalTree(root->left) && isUnivalTree(root->right);

参照コード:

bool isUnivalTree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    if(root->right && root->val!=root->right->val)
    {
        return false;
    }
    if(root->left && root->val!=root->left->val)
    {
        return false;
    }
    //以上三个if为递归的出口
    return isUnivalTree(root->left) && isUnivalTree(root->right);//分治,安排任务下去
}

書いた後で少し信じられない場合は、再帰的な展開図を描き、頭の中で再帰的な手順を実行する必要があります。

再帰を初めて書くことは、描くことによって理解する方が良いです。

3.2本の木が同じかどうかを確認します

bool isSameTree(struct TreeNode* p, struct TreeNode* q)

再帰的なアイデア:

pが空でqが空の場合にtrueを返します

pとqの一方が空で、もう一方が空でない場合は、falseを返します。

p-> val!= q-> val、trueを返します。

やっと:

 return isSameTree(p->left,q->left)
    &&isSameTree(p->right,q->right);

参照コード:

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

4.対称二分木

bool isSymmetric(struct TreeNode* root)

再帰的なアイデア:ルートがNULLの場合、trueを返します。

左側のサブツリーと右側のサブツリーの2つのツリーが対称であると判断すると、ここでの関数プロトタイプには1つのルートしか含まれておらず、明らかに機能しません。ここで、サブ関数を書き直します。

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)

左と右の両方がNULLに等しい場合、2つのツリーは対称です。

一方が空でもう一方が空でない場合、それは非対称です。

どちらも空でない場合:left-> val!= right-> valの場合、falseを返します。

やっと:

   return  _isSymmetric(left->left,right->right)
            &&_isSymmetric(left->right,right->left);

参照コード:

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

bool isSymmetric(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    return _isSymmetric(root->left,root->right);
}

 5.別のツリーのサブツリー

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)

トピックの説明:それはそれ自身のサブツリーと見なすことができます 

再帰的な書き込み:

サブツリーであるかどうかを判断するには、それ自体から始めて、上記の質問3を使用して、2つのツリーが同じコードを持っているかどうかを判断します。

もしも:

 if(isSameTree(root,subRoot))
 {
    return true;
 }

もう一度判断してください:

return isSubtree(root->right,subRoot)
           ||isSubtree(root->left,subRoot);

ただし、root == NULLと記述することを忘れないでください。そうしないと、root-> rightが失敗し、再帰的な終了がなくなります。

参照コード:


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

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(isSameTree(root,subRoot))
    {
        return true;
    }
    if(root==NULL)
    {
        return false;
    }
    return isSubtree(root->right,subRoot)
           ||isSubtree(root->left,subRoot);
}

6.二分木探索

 これは、ioタイプの質問であるNiuKeからの質問です。

入力:

char string[100];
scanf("%s",string);

まず、文字列の連鎖バイナリツリーを構築します。これは事前注文文字列であるため、事前注文トラバーサルで受信できます。

参照コード:

TreeNode* CreatBinaryTree(char* s,int* i)
{
    if(s[*i]=='#')
    {
        (*i)++;
        return NULL;
    }
    TreeNode* root=(TreeNode*)malloc(sizeof(TreeNode));
    root->val=s[*i];
    (*i)++;
    root->left=CreatBinaryTree(s,i);
    root->right=CreatBinaryTree(s,i);
    return root;
}

二分木を構築した後、順序通りの走査を使用します。

参照コード:

void PrevOrder(TreeNode* root)
{
    if(root==NULL)
    {
        return;
    }
    PrevOrder(root->left);
    printf("%c ",root->val);
    PrevOrder(root->right);
}

おすすめ

転載: blog.csdn.net/m0_62171658/article/details/124066705
おすすめ