二叉树的构建+遍历+判断是否完全二叉树+结点个数计算(c语言)

在这里插入图片描述

BTree.h 头文件

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);

// 层序遍历
//---------------------------
typedef struct QueueNode{//队列的每个节点有data和*next
	BTNode* data;
	struct QueueNode* next;
}QueueNode;
typedef struct QueueList{   //整个队列 有队头和队尾
	QueueNode*_front;
	QueueNode*_tail;
}Queue;
BTNode* QueueFront(Queue*q);
//--------------------------
void BinaryTreeLevelOrder(BTNode* root);
//====================================================

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

BTree.c

#include"BTree.h"

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a,  int* pi){
	if (a[*pi] == '#'){
		++(*pi);
		return NULL;
	}
	BTNode*root = (BTNode*)malloc(sizeof(BTNode));
	root->data = a[*pi];
	++(*pi);
	root->left = BinaryTreeCreate(a, pi);
	root->right = BinaryTreeCreate(a, pi);
	return root;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode* root){
	if (root == NULL)return;
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root){
	if (root == NULL)return 0;
	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
// 二叉树叶子节点个数
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);
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k){
	if (root == NULL)return 0;
	if (k == 1)return 1;
	return BinaryTreeLevelKSize(root->left, k - 1)+BinaryTreeLevelKSize(root->right,k-1);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x){
	if (root == NULL)return NULL;
	if (root->data == x)return root;  //这两种情况针对一开头

	BTNode*node = BinaryTreeFind(root->left, x);
	if (node)return node;
	node = BinaryTreeFind(root->right, x);
	if (node)return node;
	return  NULL;
}
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root){
	if (root == NULL)return;
	printf("前序遍历:%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root){
	if (root == NULL)return;
	BinaryTreeInOrder(root->left);
	printf("中序遍历:%c ", root->data);
	BinaryTreeInOrder(root->right);
	
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root){
	if (root == NULL)return;
	BinaryTreeInOrder(root->left);
	BinaryTreeInOrder(root->right);
	printf("后序遍历:%c ", root->data);
}

// 层序遍历 (要用列表:构建 初始化 入队列 判空 出队列)
void QueueInit(Queue*q){  //队列初始化
	assert(q);
	q->_front = NULL;
	q->_tail = NULL;
}
void QueuePush(Queue*q, BTNode*data){  //这里push进来的不是一个char而是一个BTNode
	assert(q);
	QueueNode*newNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newNode == NULL){
		printf("内存不足!");
		exit(-1);
	}
	newNode->data = data;
	newNode->next = NULL;
	if (q->_front == NULL)q->_front = q->_tail = newNode;
	else{
		q->_tail->next = newNode;
		q->_tail = newNode;
	}
}
int QueueEmpty(Queue*q){ //0空 1非空
	assert(q);
	if (q->_front == q->_tail&&q->_front==NULL)return 1; //注意这个q->_front==NULL的的情况;
	else return 0;
}
void QueuePop(Queue*q){  //先进先出 所以是对头出队列
	assert(q);
	assert(q->_front);
	QueueNode*next = q->_front->next;
	free(q->_front);
	q->_front = next;
	if (next == NULL){
		q->_tail = NULL;
	}
}
BTNode* QueueFront(Queue*q){  //获取队列头部元素(这个“元素”在此题中是树结点
	assert(q);
	assert(q->_front);
	return q->_front->data;
}
//核心思想:取root开始入队列,然后打印结点值并出队列,紧接着将孩子
//入队列,再出左孩子 入左孩子的孩子,出右孩子 入右孩子的孩子
void BinaryTreeLevelOrder(BTNode* root){
	Queue q;
	QueueInit(&q); 
	if (root == NULL)return;  
	QueuePush(&q, root);
	while (!QueueEmpty(&q)){
		BTNode*front= QueueFront(&q);  //取队头的结点(把结点当作队列中某个结点的数据)
		printf("%c ", front->data);
		QueuePop(&q); 
		if (front->left) QueuePush(&q, front->left);
		if (front->right)QueuePush(&q, front->right);
	}
	printf("\n");
}
// 判断二叉树是否是完全二叉树
//核心思想:一旦发现入队列的结点为NULL,那就循环出队列看看队列里是否有
//非NULL结点,如果有则不是完全二叉树;
int BinaryTreeComplete(BTNode* root){
	Queue q;
	QueueInit(&q);
	if (root == NULL)return 1;
	QueuePush(&q,root);
	while (!QueueEmpty(&q)){
		BTNode*front = QueueFront(&q);
		
		if (front == NULL)break;
		QueuePop(&q);
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}
	while (!QueueEmpty(&q)){ 
		BTNode*front = QueueFront(&q);  
		
		if (front)return 0;
		QueuePop(&q);
	}
	return 1;
}

test.c

#include"BTree.h"
///==============TestBinaryTreeCreate===========================
void PreOrder(BTNode*root){
	if (root == NULL)return ; 
	printf("%c ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
void TestBinaryTreeCreate(){
	char str[] = { 'a', 'b', 'c', '#', '#', 'd', 'e', '#', 'g', '#', '#', 'f', '#', '#', '#' };
	int i = 0;
	BTNode*root = BinaryTreeCreate(str, &i);
	int size=BinaryTreeLeafSize(root);
	printf("叶子结点个数:%d\n ", size);
	int nums=BinaryTreeLevelKSize(root, 4);//第二层结点个数
	printf("第k层结点个数:%d\n", nums);
	BTNode*ret= BinaryTreeFind(root, 'g');
	if (ret == NULL) printf("没有该结点!");
	else printf("找到该结点,是:%c\n", ret->data);

	//PreOrder(root); 

	BinaryTreeLevelOrder(root); //层序遍历 (广度优先遍历)
	int isBTC=BinaryTreeComplete(root);  //判断是否是完全二叉树
	printf("是否是完全二叉树:%d ", isBTC);
}
//----------------------------------------------------------------

int main(){
	TestBinaryTreeCreate();
	system("pause");
	return 0;
}

复习版本

BTree.h

#include<iostream>
#include<assert.h>
typedef char DataType;
typedef struct BinaryTreeNode
{
	DataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode; 
BTNode* BinaryTreeCreate(DataType* a, int *pi) //前序遍历方式构建二叉树
{
	if (a[*pi] == '#')
	{
		++(*pi);
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	root->_data = a[*pi];  // a[*pi];
	++(*pi); //++(*pi);
	root->_left = BinaryTreeCreate(a, pi);
	root->_right = BinaryTreeCreate(a, pi);

	return root;
}
//      前序遍历
void PrevOrder(BTNode*root)
{
	if (root == NULL)
	{
		printf("# ");
		return;
	}
	printf("%c ", root->_data);
	PrevOrder(root->_left);
	PrevOrder(root->_right);
}
void InOrder(BTNode*root)
{
	if (root == NULL)
	{
		printf("# ");
		return;
	}
	InOrder(root->_left);
	printf("%c ", root->_data);
	InOrder(root->_right);
}
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("# ");
		return;
	}
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_data);
}
int TreeSize1(BTNode* root) // 写法一:
{
	if (root == NULL)
	{
		return 0;
	}
	static int size = 0;
	++size;
	TreeSize1(root->_left);   // 相当于以前序遍历的方式计算size
	TreeSize1(root->_right);
	return size;
}
void TreeSize2(BTNode* root, int *psize)  // 写法二:返回型参数
{
	if (root == NULL)
	{
		return;
	}
	else
	{
		++(*psize);
	}
	TreeSize2(root->_left,psize);
	TreeSize2(root->_right,psize);

}
int TreeSize(BTNode* root)  // 写法三: 
{
	if (root == NULL)
	{
		return 0;
	}
	return 1+TreeSize(root->_left) + TreeSize(root->_right);
}

// 第k层结点个数
int BinaryTreeLevelKSize(BTNode*root, int k)
{
	if (k == 0)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left,k-1) + BinaryTreeLevelKSize(root->_right,k-1);
}

// 层序遍历
// 需要构建queue队列来辅助层序遍历;
typedef struct QueueNode
{
	BTNode* node;
	struct QueueNode* next;
}QueueNode;
typedef struct QueueList    // QueueList由QueueNode构成,QueueNode由BTNode 和一个next指针构成;
{
	QueueNode* _front;
	QueueNode* _tail;
}Queue;
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = NULL;
	q->_tail = NULL;
}
bool QueueEmpty(Queue* q)
{
	//return (q->_front == NULL);  //
	assert(q);
	if (q->_front == q->_tail&&q->_front == NULL)return 1;
	else return 0;
}
BTNode* QueueFront(Queue* q)
{
	assert(q);
	assert(q->_front);
	return q->_front->node;
}
void QueuePop(Queue* q)
{
	assert(q);
	assert(q->_front);
	QueueNode* next = q->_front->next;
	free(q->_front);
	q->_front = next;
	// 倘若原来queue就一个BTNode; 那么现在就要变成空了
	if (next == NULL)
	{
		q->_tail = NULL;
	}
}
void QueuePush(Queue*q, BTNode* node)
{
	assert(q);
	QueueNode* newQueueNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newQueueNode == NULL)                                                       
	{
		printf("内存不足");
		exit(-1);
	}
	newQueueNode->node = node;
	newQueueNode->next = NULL;
	if (q->_front == NULL)  // 如果原先queue里没有结点
	{
		q->_front = q->_tail = newQueueNode;
	}
	else
	{
		q->_tail->next = newQueueNode;
		q->_tail = newQueueNode;
	}
}


void BinaryTreeLevelOrder(BTNode* root)  // 层序遍历(要借助队列来实现)  // 这里的队列自己写的
{
	Queue q; 
	QueueInit(&q);   
	if (root == NULL)return;
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_data);

		QueuePop(&q);
		if (front->_left)  // 这个判断不能少
			QueuePush(&q, front->_left);
		if (front->_right)
			QueuePush(&q, front->_right);
	}
	printf("\n");
}

#include<queue>
using namespace std;

 写法二
//void BinaryTreeLevelOrder(BTNode* root)  // 层序遍历(要借助队列来实现)  // 用库里的队列
//{
//	std::queue<BTNode> q;
//	if (root == NULL)return;
//	q.push(*root);
//	while (!q.empty())
//	{
//		BTNode front = q.front();
//		printf("%c ",(&front)->_data);
//
//		q.pop();
//		if ((&front)->_left)  // 这个判断不能少 
//			q.push(*((&front)->_left));
//		if ((&front)->_right)
//			q.push(*((&front)->_right));
//	}
//	printf("\n");
//}
// 写法三 用指针数组
// 这种思想类似于快慢指针,in相当于快指针只负责一直往数组里写 in不断一直++,而out不紧不慢,从数组0开始依次向外读;
void BinaryTreeLevelOrder3(BTNode* root)
{
	BTNode* temp[100];
	int in = 0;
	int out = 0;
	temp[in++] = root;
	while (in > out)       
	{
		if (temp[out])
		{
			cout << temp[out]->_data << " ";
			temp[in++] = temp[out]->_left;
			temp[in++] = temp[out]->_right;
		}
		out++;

	}
}
//======================================================================
// 判断是否是完全二叉树
// 思路: 从根节点开始进队列,出根节点后,进1孩子,2孩子;出1,进去3,4;出2,咦?2是空,好那就看目前队列里有没有元素;
int BinaryTreeComplete(BTNode* root){
	Queue q;
	QueueInit(&q);
	if (root == NULL){
		return 1;
	}
	QueuePush(&q, root);
	while (!QueueEmpty(&q)){
		BTNode*front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL) break; //跳出这个while循环
		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}
	while (!QueueEmpty(&q)){
		BTNode*front = QueueFront(&q);
		QueuePop(&q);
		if (front) return 0;
	}
	return 1;
}

BTree_test.cc

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<stdlib.h>
#include"BTree.h"

void test4()
{
	char arr[] = { 'A', 'B', 'D', '#', '#', 'E', '#', 'H', '#', '#', 'C', 'F', '#', '#', 'G', '#', '#' }; //"ABD##E#H##CF##G##"
	int a = 0; // 相当于其实遍历序号
	BTNode* root = BinaryTreeCreate(arr, &a);  // 按照前序遍历来构建的;
	PrevOrder(root);   //前序遍历
	printf("\n");
	InOrder(root);
	printf("\n");
	PostOrder(root);
	printf("\n");

	// 方式1;
	//int Tree_size = TreeSize(root);
	// 方式二:==================
	int Tree_size = 0;
	TreeSize2(root,&Tree_size); // 返回型参数 Tree_size;
	//==========================
	printf("结点个数:%d\n", Tree_size);

	int K_size = BinaryTreeLevelKSize(root, 3);
	printf("第k层 结点个数:%d\n", K_size);
}
void test5() // 层序遍历
{
	char arr[] = { 'A', 'B', 'D', '#', '#', 'E', '#', 'H', '#', '#', 'C', 'F', '#', '#', 'G', '#', '#' }; //"ABD##E#H##CF##G##"
	int a = 0; // 相当于其实遍历序号
	BTNode* root = BinaryTreeCreate(arr, &a);  // 按照前序遍历来构建的;
	BinaryTreeLevelOrder(root);

	int ret = BinaryTreeComplete(root);// 判断是否是完全二叉树
	printf("%d\n", ret);

}

int main()
{
	test4();
	test5();
	
	system("pause");
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值