データ構造 C コード 6.1: バイナリ ツリーの構築とトラバース

学習目標: バイナリ ツリーの構築と走査方法を学ぶ

学習ガイド:ファンシェンのコード

学習課題:

  1. コードをコピーする
  2. 学習成果カタログ

    1 つの完全なコード

    2 テスト結果

    3 グラフィック

コードの説明:

  1. バイナリ ツリーの深いトラバーサルはスタックを使用するため、コードは非常に簡潔ですが、スタックを使用しない方法は、対応するコード データ構造C コード 6.x: バイナリ ツリー トラバーサルを実現するために自分でスタックを構築します
  2. キューは階層の走査に使用されます。今回は、循環キューがスペースを正常に再利用できるかどうかを確認するために、意図的に少ないスペースを割り当てます。
  3. スタックは文字列からバイナリ ツリーを構築するためにも使用され、バイナリ ツリーの非圧縮ストレージもここで確認できます。
  4. バイナリ ツリーは、重要なタイプのツリー構造です。多くの現実的な問題から抽象化されたデータ構造は二分木の形をとることが多く、一般的な木であっても二分木への変換は容易であり、二分木の記憶構造やアルゴリズムも比較的単純であるため、二分木は特に重要です。二分木の特徴は、各ノードが最大 2 つのサブツリーしか持てず、左点と右点が存在することです。バイナリ ツリーは、n 個の有限要素のコレクションです。コレクションは空であるか、ルートと呼ばれる要素と、それぞれ左サブツリーおよび右サブツリーと呼ばれる 2 つの素のバイナリ ツリーで構成されます。これは順序付きツリーです。集合が空の場合、二分木は空二分木と呼ばれます。二分木では、要素はノードとも呼ばれます。
  5. フロント、ミドル、バックオーダーのトラバーサルを手動で追加しました (私は再帰を使用することを好みます)。

勉強の時間:

2022.5.24

1 つの完全なコード

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

#define MAXSIZE 5

//二叉树的结构 
typedef struct BTnode
{
	char element;
	struct BTnode *left;
	struct BTnode *right;	
}*BTnodePtr;
//队列
typedef struct BTNodePtrQueue
{
	BTnodePtr *nodePtrs;
	int front;
	int rear;
}*QueuePtr;
/**
 * @brief 初始化队列
 * 
 * @return 
 */
QueuePtr initQueue()
{
	QueuePtr resultPtr = (QueuePtr)malloc(sizeof(struct BTNodePtrQueue));
	resultPtr->nodePtrs = (BTnodePtr*)malloc(MAXSIZE * (sizeof(BTnodePtr)));
	resultPtr->front = 0;
	resultPtr->rear = 1;
	return resultPtr;	
} 
/**
 * @brief 判断是否为空队列
 * 
 * @param paraQueuePtr 
 * 
 * @return 
 */
int isQueueEmpty(QueuePtr paraQueuePtr)
{
	if ((paraQueuePtr->front + 1) % MAXSIZE == paraQueuePtr->rear) 
	{
		return 1;
	}
	
	return 0;
}
/**
 * @brief 添加节点
 * 
 * @param Queue 
 * @param newBTnodePtr 
 */
void enqueue(QueuePtr Queue,BTnodePtr newBTnodePtr)
{
	if((Queue->rear +1)%MAXSIZE == (Queue->front)%MAXSIZE )
	{
		printf("错误,队满,无法添加节点.\n");
		return ; 
	}	
	Queue->nodePtrs [Queue->rear] = newBTnodePtr;
	Queue->rear = (Queue->rear+1)%MAXSIZE;
	printf("添加 节点%c 成功.\n", newBTnodePtr->element);
	
} 
/**
 * @brief 删除节点
 * 
 * @param Queue 
 * 
 * @return 
 */
BTnodePtr deQueue(QueuePtr Queue)
{
	if(isQueueEmpty(Queue))
	{
		printf("错误,队空,无法删除节点.\n");
		return Queue->nodePtrs [Queue->front];
	}
	Queue->front = (Queue->front +1)%MAXSIZE;
	printf("删除 节点%c 成功.\n",Queue->nodePtrs [Queue->front]->element);
	
	return  Queue->nodePtrs [Queue->front];
} 
/**
 * @brief 创建并初始化结点 
 * 
 * @param newElement 
 * 
 * @return 
 */
BTnodePtr constructBTnode(char newElement)
{
	BTnodePtr newPtr = (BTnodePtr)malloc(sizeof(struct BTnode));
	newPtr->element = newElement;
	newPtr->left = NULL;
	newPtr->right  = NULL;
	return newPtr;
}
/**
 * @brief 创建并初始化二叉树
 * 
 * @param newString 
 * 
 * @return 
 */
BTnodePtr stringToBTree(char *newString)
{
	int i=0;
	char ch;
	
	//使用队列管理指针
	QueuePtr Queue = initQueue();
	
	BTnodePtr resultHeader;//根
	BTnodePtr tempParent,tempLeftChlid,tempRightChild;
	
	ch = newString[i];
	resultHeader = constructBTnode(ch);
	enqueue(Queue,resultHeader);
	
	while(!isQueueEmpty(Queue))
	{
		tempParent = deQueue(Queue);
		//左子节点
		i++;
		if(newString[i] == '#')
		{
			tempParent->left = NULL;
		}
		else
		{
			tempLeftChlid = constructBTnode(newString[i]);
			enqueue(Queue,tempLeftChlid);
			tempParent->left = tempLeftChlid;
		}
		//右子节点
		i++;
		if(newString[i] == '#')
		{
			tempParent->right = NULL;
		}
		else
		{
			tempRightChild = constructBTnode(newString[i]);
			enqueue(Queue,tempRightChild);
			tempParent->right = tempRightChild;
		}
		
	} 
	//返回根节点
	return resultHeader;	
}
/**
 * @brief 层序遍历
 * 
 * @param newTreePtr 
 */
void levelwise(BTnodePtr newTreePtr)
{
	char string[100];
	int i = 0;
	//使用队列管理指针
	QueuePtr Queue = initQueue();
	BTnodePtr tempNodePtr;
	
	enqueue(Queue,newTreePtr);
	while(!isQueueEmpty(Queue))
	{
		tempNodePtr = deQueue(Queue);
		string[i] = tempNodePtr->element ;
		i++;
		if(tempNodePtr->left != NULL)
		{
			enqueue(Queue,tempNodePtr->left);
		}
		if(tempNodePtr->right  != NULL)
		{
			enqueue(Queue,tempNodePtr->right);
		}
	}
	string[i] = '\0';
	printf("层序遍历:%s\n",string);
} 
/**
 * @brief 前序遍历二叉树
 * 
 * @param newTreePtr 
 * 
 * @return 
 */
int preVisitBiTree(BTnodePtr newTreePtr)
{
	if(newTreePtr)
	{
		/* 先遍历根节点 */
		printf("%c",newTreePtr->element);
		
		/* 遍历左子树 */
		preVisitBiTree(newTreePtr->left);
		
		/* 遍历右子树 */
		preVisitBiTree(newTreePtr->right);
		
	}
	return 0;
}
/**
 * @brief 中序遍历二叉树
 * 
 * @param newTreePtr 
 * 
 * @return 
 */
int inVisitBiTree(BTnodePtr newTreePtr)
{
	if(newTreePtr)
	{
		/* 遍历左子树 */
		preVisitBiTree(newTreePtr->left);
		
		
		/* 先遍历根节点 */
		printf("%c",newTreePtr->element);
		
		/* 遍历右子树 */
		preVisitBiTree(newTreePtr->right);
		
	}
	return 0;
}
/**
 * @brief 后序遍历二叉树
 * 
 * @param newTreePtr 
 * 
 * @return 
 */
int postVisitBiTree(BTnodePtr newTreePtr)
{
	if(newTreePtr)
	{
		/* 遍历左子树 */
		preVisitBiTree(newTreePtr->left);
		
		
		/* 遍历右子树 */
		preVisitBiTree(newTreePtr->right);
		
		
		/* 先遍历根节点 */
		printf("%c",newTreePtr->element);
		
	}
	return 0;
}

void BinaryTreeTest(){
	printf("---- BinaryTreeTest 测试开始 ----\n");
	printf("初始化二叉树\n");
	BTnodePtr tempHeader;
	char* tempString = "acde#bf######";
	tempHeader = stringToBTree(tempString);
	printf("进行层序遍历\n");
	levelwise(tempHeader);
	printf("\n前序遍历:");
	preVisitBiTree(tempHeader);
	printf("\n中序遍历:");
	inVisitBiTree(tempHeader);
	printf("\n后序遍历:");
	postVisitBiTree(tempHeader);
	printf("\n");
	printf("---- BinaryTreeTest 测试结束 ----\n");
}

int main(){
	BinaryTreeTest();
	return 1;
}

2 テスト結果

---- BinaryTreeTest 测试开始 ----
初始化二叉树
添加 节点a 成功.
删除 节点a 成功.
添加 节点c 成功.
添加 节点d 成功.
删除 节点c 成功.
添加 节点e 成功.
删除 节点d 成功.
添加 节点b 成功.
添加 节点f 成功.
删除 节点e 成功.
删除 节点b 成功.
删除 节点f 成功.
进行层序遍历
添加 节点a 成功.
删除 节点a 成功.
添加 节点c 成功.
添加 节点d 成功.
删除 节点c 成功.
添加 节点e 成功.
删除 节点d 成功.
添加 节点b 成功.
添加 节点f 成功.
删除 节点e 成功.
删除 节点b 成功.
删除 节点f 成功.
层序遍历:acdebf

前序遍历:acedbf
中序遍历:ceadbf
后序遍历:cedbfa
---- BinaryTreeTest 测试结束 ----

3 グラフィック

レイヤー順序のトラバーサル: バイナリ ツリーを階層化し、各レイヤーを左から右にトラバースします。

おすすめ

転載: blog.csdn.net/qq_61649579/article/details/124952433