【データ構造】二分木の格納構造と初・中・後順再帰探索アルゴリズム(C言語)

1. 木と二分木

1.1 ツリーの基本概念

ツリーは、 n (n>=0) ノードの有限集合 T です。n = 0 のときは空木と呼び、n>0 のとき集合は次の条件を満たす: ①直接の先行者を持たないが、0 個以上の直接の
存在する必要があります。② 残りの n-1 ノードは、m (m>=0) 個の互いに素な有限集合 T1、T2、T3、...、Tn に分割できます。ここで、Ti はルートのサブツリーと呼ばれる別の木です。各サブツリーのルート ノードには、直前の先行ノードが 1 つだけありますが、直後の後続ノードは 0 個以上あります。(1)ノード: データ要素と、他のノードを指すいくつかのブランチ情報を含みます。(2)ノードの次数: ノードのサブツリーの数をこのノードの次数と呼びます。(3)葉ノード: 次数が 0 のノード、つまり後続ノードのないノードで、ターミナル ノードとも呼ばれます。(4)分岐ノード: 次数が 0 でないノード。非終端ノードとも呼ばれます。(5)ノード レベル: ルート ノードから定義され、ルート ノードのレベルは 1、ルートの直下のレベルは 2、というようになります。(6)ノードの層順番号付け: ツリー内のノードを、上層から下層へ、同じ層内で左から右へと直線的な順序で並べ、順番に連続する自然番号を割り当てます。(7)ツリーの次数: ツリー内のすべてのノードの次数の最大値。(8)

ツリー表現






ツリーの高さ (深さ) : ツリー内のすべてのノードのレベルの最大値。
(9)順序木: 木 T において、部分木 Ti に系列がある場合、それを順序木と呼ぶ。
(10): m (m>=0) の互いに素な木の集まり。空でないツリーのルート ノードを削除すると、そのツリーはフォレストになります。それ以外の場合は、統合されたルート ノードをフォレストに追加すると、フォレストはツリーになります。
(11)同型性: 2 つのツリーの場合、ノードの名前を適切に変更することにより、2 つのツリーが完全に等しくなる (対応するノードが等しく、対応するノード間の相関も等しい) 場合、2 つのツリーは同型と呼ばれます。
(12)子ノード: ノードの直接の後継者は、ノードの子ノードと呼ばれます。たとえば、B と C は A の子です。
(13)親ノード: ノードの直接の先行ノードは、ノードの親ノードと呼ばれます。たとえば、A は B と C の親です。
(14)兄弟ノード: 同じ親ノードの子ノードは、兄弟ノードと呼ばれます。たとえば、H、I、および G は互いに兄弟です。
(15) Cousins : 父親が兄弟またはいとこであるノードは、Cousin ノードと呼ばれます。たとえば、ノード E、G、および H は互いにいとこです。
(16)祖先ノード: ノードの祖先ノードとは、ルート ノードからノードまでのパス上のすべてのノードを指します。たとえば、ノード K の祖先は A、B、E です。
(17)子孫ノード: ノードの直接の後継者と間接の後継者を、そのノードの子孫ノードと呼びます。たとえば、ノード D の子孫は H、I、J、M です。
(18)シニア: このノードより層番号が小さいノードは、このノードの先行ノードと呼ばれます。たとえば、ノード A、B、C、および D はすべて、ノード E の先行ノードと呼ぶことができます。
(19)子孫: 層番号がこのノードよりも大きいノードは、このノードの子孫と呼ばれます。たとえば、ノード K、L、および M はすべて、ノード E の子孫と呼ぶことができます。

1.2 二分木の基本概念

次の 2 つの条件を満たす木構造を二分木と呼びます。
①各ノードの次数が2以下。
②各ノードの子ノードの順序を任意に逆にすることはできません。
したがって、バイナリ ツリーの各ノードには 0、1、または 2 つの子しか含めることができず、各子には左と右のポイントがあります。左側の子は左の子、右側の子は右の子と呼ばれます。
完全二分木: 深さが k で (2^k) -1 ノードの二分木。フル バイナリ ツリーでは、ノードの各レベルがフルです。つまり、ノードの各レベルに最大数のノードがあります。
完全二分木: ノード 1 ~ n の位置番号が完全二分木のノード 1 ~ n の位置番号と 1 対 1 で対応している場合、深さ k および n ノードの二分木高さ、完全な二分木です。
二分木の性質プロパティ
1 : 二分木の i 番目の層には最大 2^(i-1) 個のノード (i>=1) があります。
プロパティ 2 : 深さ k の二分木には、最大で (2^k) -1 個のノード (k>=1) があります。
性質 3 : 任意の二分木 T について、終端ノードの数を n0、次数が 2 のノードの数を n2 とすると、n0=n2+1 です。
性質 4 : n 個のノードを持つ完全な二分木の深さは ⌊log2 (n)⌋+1 です。
性質 5 : n 個のノードを持つ完全な二分木の場合、二分木のすべてのノードが上から下、左から右の順に 1 から番号付けされている場合、シーケンス番号 i を持つ任意のノードについて、次のようになります。
① i = 1 の場合、シリアル番号 i のノードはルート ノードであり、親ノードはありません。i > 1 の場合、シリアル番号 i のノードの親ノードのシリアル番号は ⌊i / 2⌋ です。
② 2i>n の場合、通し番号 i のノードには左子がなく、2i<=n の場合、通し番号 i のノードの左子の通し番号は 2i です。
③ 2i+1>n の場合、通し番号 i のノードには右の子がなく、2i+1<=n の場合、通し番号 i のノードの右の子の通し番号は 2i+1 です。

2. 二分木の格納構造と探索アルゴリズム

2.1 二分木の格納構造

どのバイナリ ツリーでも、各ノードには親ノードが 1 つだけあり (ルートを除く)、最大で 2 つの子があるため、各ノードには少なくとも 3 つのフィールド (データ フィールド、左の子フィールド、右の子フィールド) が含まれます。
二分木ノード構造このうち、LChild フィールドはノードの左側の子を指し、Data フィールドはノードの情報を記録し、RChild フィールドはノードの右側の子を指します。このノード構造によって形成される二分木は、二分連結リストと呼ばれます。
二項連結リスト
コード

/*二叉树的链式存储结构*/
typedef char DataType;
typedef struct Node {
    
    
	DataType data;
	struct Node* LChild;
	struct Node* RChild;
}BiTNode, * BiTree;

2.2 二分木の前順、順順、後順トラバーサル

事前順序トラバーサル(DLR) 操作プロセス:
① ルート ノードを訪問する;
② 左側のサブツリーを事前順序でトラバースする;
③ 右側のサブツリーを事前順序でトラバースする。
順序トラバーサル(LDR) 操作プロセス:
① 左側のサブツリーを順序どおりにトラバースする;
② ルート ノードにアクセスする;
③ 右側のサブツリーを順序どおりにトラバースする。
ポスト オーダー トラバーサル(LRD) 操作プロセス:
① ポスト オーダーで左サブツリーをトラバースする;
② ポスト オーダーで右サブツリーをトラバースする;
③ ルート ノードにアクセスする。
二分木トラバーサル二分木探索コード

/*先序遍历二叉树(递归)*/
void PreOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		printf("%c ", bt->data);		//输出结点值
		PreOrder(bt->LChild);			//先序遍历左子树
		PreOrder(bt->RChild);			//先序遍历右子树
	}
}

/*中序遍历二叉树(递归)*/
void InOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		InOrder(bt->LChild);			//中序遍历左子树
		printf("%c ", bt->data);		//输出结点值
		InOrder(bt->RChild);			//中序遍历右子树
	}
}

/*后序遍历二叉树(递归)*/
void PostOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		PostOrder(bt->LChild);			//后序遍历左子树
		PostOrder(bt->RChild);			//后序遍历右子树
		printf("%c ", bt->data);		//输出结点值
	}
}

2.3 トラバーサルアルゴリズムの適用

2.3.1 バイナリ リンク リストの形式で格納されたバイナリ ツリーを作成する (拡張された順序でシーケンスをたどる)

/*建立二叉链表方式存储的二叉树(按扩展先序遍历序列)*/
void CreateBiTree(BiTree* bt) {
    
    
//'.'表示空子树
	char ch;
	ch = getchar();
	if (ch == '.')								//'.'表示空子树
		*bt = NULL;
	else {
    
    
		(*bt) = (BiTree)malloc(sizeof(BiTNode));
		(*bt)->data = ch;						//生成根结点
		CreateBiTree(&((*bt)->LChild));			//构造左子树
		CreateBiTree(&((*bt)->RChild));			//构造右子树
	}
}

2.3.2 二分木の葉ノードを出力するための事前順序走査

/*先序遍历输出二叉树中叶子结点*/
void PreOrderLeaf(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		if (bt->LChild == NULL && bt->RChild == NULL)
			printf("%c ", bt->data);			//输出叶子结点值
		PreOrderLeaf(bt->LChild);				//先序遍历左子树
		PreOrderLeaf(bt->RChild);				//先序遍历右子树
	}
}

2.3.3 葉ノード数を数えるポストオーダートラバーサル

/*后序遍历统计叶子结点数目*/
int count = 0;
void LeafCount(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		LeafCount(bt->LChild);
		LeafCount(bt->RChild);
		if (bt->LChild == NULL && bt->RChild == NULL)
			count++;
	}
}

2.3.4 バイナリ ツリーの高さを見つけるためのポスト オーダー トラバーサル

/*后序遍历求二叉树高度*/
int PostTreeDepth(BiTree bt) {
    
    
	int hl = 0, hr = 0, max;
	if (bt != NULL) {
    
    
		hl = PostTreeDepth(bt->LChild);
		hr = PostTreeDepth(bt->RChild);
		max = hl > hr ? hl : hr;
		return (max + 1);
	}
	else
		return 0;
}

2.3.5 二分木をツリー形式で出力する

/*按树状打印二叉树*/
void PrintTree(BiTree bt, int nLayer) {
    
    
	if (bt == NULL)
		return;
	PrintTree(bt->RChild, nLayer + 1);
	for (int i = 0; i < nLayer; i++)
		printf("  ");
	printf("%c\n", bt->data);					//按逆中序输出结点,用层深决定的左右位置
	PrintTree(bt->LChild, nLayer + 1);
}

2.4 二分木操作の完全な実装コード

/*二叉树的存储结构及基本运算*/

# include<stdio.h>
# include<malloc.h>
# define TRUE 1
# define FALSE 0

/*二叉树的链式存储结构*/
typedef char DataType;
typedef struct Node {
    
    
	DataType data;
	struct Node* LChild;
	struct Node* RChild;
}BiTNode, * BiTree;

BiTree bt;

/*建立二叉链表方式存储的二叉树(按扩展先序遍历序列)*/
void CreateBiTree(BiTree* bt) {
    
    
//'.'表示空子树
	char ch;
	ch = getchar();
	if (ch == '.')									//'.'表示空子树
		*bt = NULL;
	else {
    
    
		(*bt) = (BiTree)malloc(sizeof(BiTNode));
		(*bt)->data = ch;							//生成根结点
		CreateBiTree(&((*bt)->LChild));				//构造左子树
		CreateBiTree(&((*bt)->RChild));				//构造右子树
	}
}

/*先序遍历二叉树(递归)*/
void PreOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		printf("%c ", bt->data);				//输出结点值
		PreOrder(bt->LChild);					//先序遍历左子树
		PreOrder(bt->RChild);					//先序遍历右子树
	}
}

/*中序遍历二叉树(递归)*/
void InOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		InOrder(bt->LChild);					//中序遍历左子树
		printf("%c ", bt->data);				//输出结点值
		InOrder(bt->RChild);					//中序遍历右子树
	}
}

/*后序遍历二叉树(递归)*/
void PostOrder(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		PostOrder(bt->LChild);					//后序遍历左子树
		PostOrder(bt->RChild);					//后序遍历右子树
		printf("%c ", bt->data);				//输出结点值
	}
}

/*先序遍历输出二叉树中叶子结点*/
void PreOrderLeaf(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		if (bt->LChild == NULL && bt->RChild == NULL)
			printf("%c ", bt->data);			//输出叶子结点值
		PreOrderLeaf(bt->LChild);				//先序遍历左子树
		PreOrderLeaf(bt->RChild);				//先序遍历右子树
	}
}

/*后序遍历统计叶子结点数目*/
int count = 0;
void LeafCount(BiTree bt) {
    
    
	if (bt != NULL) {
    
    
		LeafCount(bt->LChild);
		LeafCount(bt->RChild);
		if (bt->LChild == NULL && bt->RChild == NULL)
			count++;
	}
}

/*后序遍历求二叉树高度*/
int PostTreeDepth(BiTree bt) {
    
    
	int hl = 0, hr = 0, max;
	if (bt != NULL) {
    
    
		hl = PostTreeDepth(bt->LChild);
		hr = PostTreeDepth(bt->RChild);
		max = hl > hr ? hl : hr;
		return (max + 1);
	}
	else
		return 0;
}

/*按树状打印二叉树*/
void PrintTree(BiTree bt, int nLayer) {
    
    
	if (bt == NULL)
		return;
	PrintTree(bt->RChild, nLayer + 1);
	for (int i = 0; i < nLayer; i++)
		printf("  ");
	printf("%c\n", bt->data);					//按逆中序输出结点,用层深决定的左右位置
	PrintTree(bt->LChild, nLayer + 1);
}

int main() {
    
    
	printf("树的创建:");
	CreateBiTree(&bt);

	printf("先序遍历:");
	PreOrder(bt);

	printf("\n中序遍历:");
	InOrder(bt);

	printf("\n后序遍历:");
	PostOrder(bt);

	printf("\n叶子结点:");
	PreOrderLeaf(bt);

	LeafCount(bt);
	printf("\n叶结点数:%d", count);

	printf("\n树的高度:%d", PostTreeDepth(bt));

	printf("\n树状打印:\n");
	PrintTree(bt, 0);
	return 0;
}

2.5 走行結果

運用実績
参考:耿國華「データ構造 C言語で解説(第2版)」

データ構造の詳細については、私の「データ構造」列に従ってください: https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482

おすすめ

転載: blog.csdn.net/weixin_51450101/article/details/122742243