記事ディレクトリ
1. バイナリツリートラバーサル
以下のすべてのコードのバイナリ ツリー ノード:
typedef char BTDataType;
//二叉树结点结构体
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
1. 事前注文トラバーサル
前順、中間、後順の走査はすべて、分割統治再帰の考え方を使用して解決でき、ルート ノードとその子ノードは個別に処理されます。
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
ここでは、再帰的展開グラフのみを使用して、前順序トラバーサルを分析します。同じ考え方が、順序内および後順序でも使用されます。
2. 順序どおりの走査
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
BinaryTreeInOrder(root->left);
printf("%c ", root->data);
BinaryTreeInOrder(root->right);
}
3. ポストオーダートラバーサル
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c ", root->data);
}
4. 層順次走査
レベル順序のトラバーサルはキューを使用して実行する必要があります。バイナリ ツリーとノードが空でない場合は、それへのポインタをキューに入れる次に、キューの先頭ノードを記録し、最初にその値を出力し、次にその左右の子が空でないと判断してからキューに参加し、キューの先頭を削除して次のノードに置き換えて記録を継続します。そして印刷...キューが空になり、走査が完了するまで続きます。
たとえば、次のようなバイナリ ツリーについて考えてみましょう。
レイヤー シーケンス トラバーサルの結果は 12345 です。
まず、ルート ノード 1 をキューに入れ、1 を出力します。
次に、1 の左右の子 2 と 3 をチームに追加します。
キュー 1 の先頭を削除し、先頭を 2 に置き換えて 2 を出力します。
次に、左の子 4/2 をチームに追加します。
先頭 2 を削除し、先頭を 3 に置き換えて、3 を印刷します。
次に、右側の子 5/3 をチームに追加します。
… …
次に、このように 4 と 5 を出力して、バイナリ ツリーのレベル順序の走査を完了します。
プログラムコードは自身で作成したキューを使用しており、以下のようなコードになります。
//层序遍历
void LevelOrder(BTNode* root)
{
//创建队列
Que q;
QueueInit(&q);
//如果根节点不为空,则放进队列
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
//将队头打印
BTNode* front = QueueFront(&q);
printf("%c ", front->data);
//判断front左右节点不为空则入队
if (front->left)
QueuePush(&q, front->left);
if (front->right)
QueuePush(&q, front->right);
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
2. 二分木のノードの数と高さ
1. 二分木のノード数
分割統治法を用いて再帰的に実装されており、ルートノードが空の場合は戻り値0、空でない場合は左右のサブツリーのノード数に1を加えた値を返します。
int BinaryTreeSize(BTNode* root)
{
return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
2. 二分木の葉ノードの数
分割統治法を用いて再帰的に実装されており、ルートノードが空の場合は0を返し、ルートノードに子ノードがない場合は葉ノードであるため1を返し、それ以外の場合は、左側と右側のサブツリーにリーフ ノードを追加するだけです。
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
3. 二分木の k 番目のレベルのノードの数
k が 0 より大きいことを確認する必要があります。ルート ノードが空の場合は 0 が返されます。k が 1 に等しい場合は、1 つのレイヤーにノードが 1 つだけあり、1 が返されます。k>1 の場合、数値はk 番目の層のノードの数は、その左右の子の k 番目の子に相当します - 層 1 のノードの数を合計します。
int BinaryTreeLevelKSize(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1)
+ BinaryTreeLevelKSize(root->right, k - 1);
}
4. 二分木で値 x を持つノードを見つける
次のノードが空の場合、見つからない場合はNULLを返します ルートノードの値が探している値であればそのノードを返します 等しくない場合はその左右の子ノードを判定します見つかるまでそれぞれ。
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* ret = BinaryTreeFind(root->left,x);
if (ret)
{
return ret;
}
return BinaryTreeFind(root->right, x);
}
3. バイナリツリーの作成と破棄
1. 配列を事前順序で走査してバイナリ ツリーを作成する
ユーザーが入力したプレオーダー トラバーサル文字列を読み取り、この文字列に基づいてバイナリ ツリー (ポインタとして保存) を構築します。たとえば、次のような事前注文トラバーサル文字列: ABC##DE#G##F### ここで、「#」はスペースを表し、スペース文字は空のツリーを表します。バイナリ ツリーを確立した後、バイナリ ツリーに対して順序走査を実行し、走査結果を出力します。
#include <stdio.h>
#include<stdlib.h>
typedef char BTDataType;
typedef struct BinaryTreeNode {
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
} BTNode;
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
if (a[*pi] == '#') {
++*pi;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTDataType));
root->data = a[*pi];
++*pi;
root->left = BinaryTreeCreate(a, pi);
root->right = BinaryTreeCreate(a, pi);
return root;
}
//中序遍历
void InOrder(BTNode* root)
{
if(root==NULL)
{
return;
}
InOrder(root->left);
printf("%c ",root->data);
InOrder(root->right);
}
int main() {
char a[100];
scanf("%s",a);
int pi=0;
BTNode* root=BinaryTreeCreate(a, &pi);
InOrder(root);
return 0;
}
2. バイナリツリーの破壊
void BinaryTreeDestory(BTNode* root)
{
if (root == NULL)
{
return;
}
BinaryTreeDestory(root->left);
BinaryTreeDestory(root->right);
free(root);
}
3. 完全な二分木であるかどうかを判断します。
空のノードもキューに入るようにバイナリ ツリーのレベル順序トラバーサルを変更します。空のノードをトラバースすると、そのノードは終了します。トラバーサルの終了前に空ではないノードがある場合、それは完全なバイナリ ツリーではありません。
int BinaryTreeComplete(BTNode* root)
{
//创建队列
Que q;
QueueInit(&q);
//如果根节点不为空,则放进队列
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
if (front == NULL)
{
break;
}
QueuePush(&q, front->left);
QueuePush(&q, front->right);
QueuePop(&q);
}
//此时已经遇到空节点,如果再遇到非空节点则不是完全二叉树
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
if (front)
{
QueueDestroy(&q);
return false;
}
QueuePop(&q);
}
QueueDestroy(&q);
return true;
}
4. テストコード
以下に示すようにバイナリ ツリーを手動で構築し、コードをテストします。
テスト結果は次のようになります。
予約注文: 123874569
中間注文: 832715469
予約注文: 837259641
完全な二分木かどうか:0
ノード数:9
リーフノード数:4
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
int main()
{
// 手动构建
BTNode* node1 = BuyNode('1');
BTNode* node2 = BuyNode('2');
BTNode* node3 = BuyNode('3');
BTNode* node4 = BuyNode('4');
BTNode* node5 = BuyNode('5');
BTNode* node6 = BuyNode('6');
BTNode* node7 = BuyNode('7');
BTNode* node8 = BuyNode('8');
BTNode* node9 = BuyNode('9');
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
node2->right = node7;
node3->left = node8;
node6->right = node9;
printf("前序遍历:");
BinaryTreePrevOrder(node1);
printf("\n");
printf("中序遍历:");
BinaryTreeInOrder(node1);
printf("\n");
printf("后序遍历:");
BinaryTreePostOrder(node1);
printf("\n");
printf("层序遍历:");
LevelOrder(node1);
printf("\n");
printf("BinaryTreeComplete:%d\n", BinaryTreeComplete(node1));
printf("BinaryTreeSize:%d\n", BinaryTreeSize(node1));
printf("BinaryTreeLeafSize:%d\n", BinaryTreeLeafSize(node1));
BinaryTreeDestory(node1);
node1 = NULL;
return 0;
}
操作結果:
実行結果は予測結果と一致しています。