序文
通常の二分木の再帰的記述方法については、書くのは簡単ですが、理解するのが少し難しいので、プレオーダー、インオーダー、ポストオーダートラバーサルの基礎が必要です。この章の問題解決は、再帰的な拡張図を描くのではなく、思考とコードを提供するだけです。
1.この章の焦点
- 。単一値の二分木
- 2本の木が同じかどうかを確認します
- 対称二分木
- 別の木のサブツリー
- 二分木の構築とトラバーサル
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); }