二叉树的概念及实现

##概念
1.二叉树:
一棵二叉树是节点的一个有限集合,该集合或者为空,或者是由一个 根节点加上两颗分别称为左子树和右子树的二叉树组成。
二叉树的特点:
每个节点最多有两棵树,即二叉树不存在度大于2的节点
二叉树的子树有左右之分,其子树的次序不能颠倒
2.满二叉树:
在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子节点都在同一层上
3.完全二叉树:
如果一棵具有N个节点的二叉树的结构与满二叉树的前N个节点的结构相同,称为完全二叉树
###二叉树的性质:

  • 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2的i-1次方个节点(i>0)
  • 若规定只有根节点的二叉树深度为1,则深度为K的二叉树的最大节点数是2的k次方-1个(k>=0)
  • 对任何一棵二叉树,如果其叶结点个数为n0,度为2的非叶节点的个数为n2,则有n0 = n2 + 1
  • 具有n个节点的完全二叉树,如果按照从上至下从右至左的顺序对所有节点从0开始编号,则对于序号为i的节点有:

1.若i>0,双亲序号:(i - 1) / 2;
i = 0, i 为根节点编号,无双亲节点
2.若2i + 1 < n,左孩子序号:2i + 1,否则无左孩子
3.若2i + 2 < n,右孩子序号:2i + 2,否则无右孩子

##基本操作
采用孩子表示法对二叉树进行存储
对结构体进行封装

typedef char BTDataType;

typedef struct BinTreeNode
{
	struct BinTreeNode* _pLeft;
	struct BinTreeNode* _pRight;
	BTDataType _data;
}BTNode, *PBTNode;

存在一个数据域,存储根节点的数据
左、右指针域,分别指向左、右孩子

// BTNode.h
#pragma once

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


typedef char BTDataType;

typedef struct BinTreeNode
{
	struct BinTreeNode* _pLeft;
	struct BinTreeNode* _pRight;
	BTDataType _data;
}BTNode, *PBTNode;

// 构建二叉树的结点 
PBTNode BuyBinTreeNode(BTDataType data);

// 创建二叉树 
void CreateBinTree(PBTNode* pRoot, const BTDataType* array, int size, BTDataType invalid);

// 拷贝二叉树 
PBTNode CopyBinTree(PBTNode pRoot);

// 销毁二叉树 
void DestroyBinTree(PBTNode *pRoot);

// 前序遍历递归 
void PreOrder(PBTNode pRoot);
// 前序遍历非递归 
void PreOrderNor(PBTNode pRoot);

// 中序遍历递归 
void InOrder(PBTNode pRoot);
// 中序遍历非递归
void InOrderNor(PBTNode pRoot);


// 后序遍历递归 
void PostOrder(PBTNode pRoot);
// 后序遍历非递归
void PostOrderNor(PBTNode pRoot);


// 层序遍历 
void LevelOrder(PBTNode pRoot);

// 二叉树的镜像递归 
void MirrorBinTree(PBTNode pRoot);

// 二叉树的镜像非递归 
void MirrorBinTreeNor(PBTNode pRoot);

// 求二叉树中结点的个数 
int BinTreeSize(PBTNode pRoot);

// 获取二叉树中叶子结点的个数 
int GetLeafCount(PBTNode pRoot);

// 求二叉树中K层结点的个数 
int GetKLevelNode(PBTNode pRoot, int K);

// 求二叉树的高度 
int Height(PBTNode pRoot);

// 采用层序遍历法查找二叉树中第一个值为data的元素  找到了返回1 没找到返回0
int Find(PBTNode pRoot, PBTNode* pos, BTDataType data);

// 判断一个节点是否在一棵二叉树中
int ISNodeInBTreeNode(PBTNode pRoot, PBTNode pos);

由于二叉树的层次遍历需要用到队列所以这里包含一下队列的头文件

// queue.h
#pragma once

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

typedef PBTNode QueueElementType;

typedef struct Node
{
	QueueElementType data;
	struct Node *next;
}LinkQueueNode;

typedef struct
{
	LinkQueueNode *front;
	LinkQueueNode *rear;
}LinkQueue;

//链队列初始化
int LinkQueueInit(LinkQueue *Q);

//链队列入队操作
int LinkQueueEnter(LinkQueue *Q, QueueElementType x);

//链队列出队操作
int LinkQueueDelete(LinkQueue *Q, QueueElementType *x);


// 判断队列是否为空 空返回1,非空返回0
int IsQunueEmpty(LinkQueue *Q);

队列函数的实现

// queue.c

#include "queue.h"

//链队列初始化
int LinkQueueInit(LinkQueue *Q)
{
	//将Q初始化为一个空的链队列
	Q->front = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
	if (NULL == Q->front)
	{
		printf("内存申请失败,未完成初始化!!!\n");
		return 0;
	}
	else
	{
		Q->rear = Q->front;
		Q->front->next = NULL;
		//printf("初始化成功\n");
		return 1;
	}
}

//链队列入队操作
int LinkQueueEnter(LinkQueue *Q, QueueElementType x)
{
	//将数据元素x插入到队列中
	LinkQueueNode *NewNode;
	NewNode = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
	if (NULL == NewNode)
	{
		printf("内存申请失败!!!\n");
		return 0;
	}
	else
	{
		NewNode->data = x;
		NewNode->next = NULL;
		Q->rear->next = NewNode;
		Q->rear = NewNode;

		//printf("数据元素%d已入队!\n", x);
		return 1;
	}
}

//链队列出队操作
int LinkQueueDelete(LinkQueue *Q, QueueElementType *x)
{
	//将队列Q的对头元素出队,并存放到x所指的内存空间中
	LinkQueueNode *p;
	if (Q->front == Q->rear)
	{
		printf("空队列!\n");
		return 0;
	}
	else
	{
		p = Q->front->next;
		Q->front->next = p->next;
		if (Q->rear == p)
		{
			//对中只有一个元素p,则p出队后成为空队
			Q->rear = Q->front;
		}
		*x = p->data;
		free(p);
		//printf("队头元素已出队!!\n");
		return 1;
	}
}




// 判断队列是否为空 空返回1,非空返回0
int IsQunueEmpty(LinkQueue *Q)
{
	assert(Q);

	if (Q->front->next == NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

在二叉树的非递归前序遍历、非递归中序遍历、非递归后序遍历用到了栈的一些函数

// Stack.h

#pragma once

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

typedef PBTNode StackElementType;

typedef struct node
{
	StackElementType data;
	struct node *next;
}LinkStackNode;

typedef LinkStackNode* LinkStack;

//链栈初始化操作
void LStackInit(LinkStack top);
//链栈进栈操作
int LStackPush(LinkStack top, StackElementType x);
//链栈出栈操作
int LStackPop(LinkStack top, StackElementType *x);
// 取栈顶元素(不出栈)
StackElementType LStackTop(LinkStack top);
// 判空
int IsLStackEmpty(LinkStack top);

栈函数的实现

//Stack.c
#include "Stack.h"

//链栈初始化操作
void LStackInit(LinkStack top)
{
	top->next = NULL;
}

//链栈进栈操作
//成功返回1
//失败返回0
int LStackPush(LinkStack top, StackElementType x)
{
	//将数据元素x压入栈top中
	LinkStackNode *temp;
	temp = (LinkStackNode *)malloc(sizeof(LinkStackNode));
	if (NULL == temp)
	{
		printf("内存申请失败!!!\n");
		return 0;
	}
	temp->data = x;
	temp->next = top->next;
	top->next = temp;
	return 1;
}

//链栈出栈操作
//成功返回1
//失败返回0
int LStackPop(LinkStack top, StackElementType *x)
{
	//将栈top的栈顶元素弹出,放到x所指的存储空间中
	LinkStackNode *temp;
	temp = top->next;
	if (NULL == temp)
	{
		printf("栈为空!!!\n");
		return 0;
	}
	top->next = temp->next;
	*x = temp->data;
	free(temp);
	return 1;
}

StackElementType LStackTop(LinkStack top)
{
	LinkStackNode *temp;
	temp = top->next;
	if (NULL == temp)
	{
		printf("栈为空!!!\n");
		return 0;
	}
	else
	{
		return temp->data;
	}
}

// 判空 空返回1 非空返回0
int IsLStackEmpty(LinkStack top)
{
	if (top->next == NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

接下来是二叉树相关函数的实现源代码:

// BTNode.c

#include "BTNode.h"
#include "queue.h"
#include "Stack.h"

// 构建二叉树的结点 
PBTNode BuyBinTreeNode(BTDataType data)
{
	PBTNode NewNode = NULL;
	NewNode = (BTNode*)malloc(sizeof(BTNode)); // 动态申请节点
	if (NULL == NewNode)
	{
		printf("内存申请失败!!!\n");
		return NULL;
	}
	else
	{
		NewNode->_data = data;
		return NewNode;
	}
}

// 创建二叉树 
/*
*采用递归的思想,根据索引的不断后移,依次创建二叉树
*/
void _CreateBinTree(PBTNode* pRoot, const BTDataType* array, int size, int* index, BTDataType invalid)
{
	if (array[*index] == invalid)
	{
		// 遇到分隔符,将节点置空
		(*pRoot) = NULL;
		return;
	}
	else if ((*index) >= size)
	{
		// 索引已经超过字符串的长度 将节点置空
		(*pRoot) = NULL;
		return;
	}
	else
	{
		// 不是分隔符&&索引没越界
		(*pRoot) = BuyBinTreeNode(array[*index]); // 创建新节点
		++(*index); // 让索引后移
		// 递归创建左子树
		_CreateBinTree(&(*pRoot)->_pLeft, array, size, index, invalid);
		++(*index); // 索引后移
		// 递归创建右子树
		_CreateBinTree(&(*pRoot)->_pRight, array, size, index, invalid);
	}
}

// 创建二叉树函数,提供给外部的接口
void CreateBinTree(PBTNode* pRoot, const BTDataType* array, int size, BTDataType invalid)
{
	int index = 0; // 作为一个索引
	// 参数检验 传过来的是根节点的地址
	assert(pRoot);

	// 调用真正的创建二叉树函数创建二叉树
	_CreateBinTree(pRoot, array, size, &index, invalid);
}

// 前序遍历递归 
void PreOrder(PBTNode pRoot)
{
	if (NULL == pRoot)
	{
		// 递归出口
		return;
	}
	else
	{
		printf("%c ", pRoot->_data); // 访问根节点
		PreOrder(pRoot->_pLeft); // 递归遍历左子树
		PreOrder(pRoot->_pRight); // 递归遍历右子树
	}
}

// 前序遍历非递归 
// 利用栈
/* 算法思想
*  初始化一个栈
*  将根节点的指针入栈
*  当栈非空时,循环执行以下步骤:
*     1.取栈顶元素(元素出栈)并访问;
*     2.若该节点的右子树非空,将该节点的右子树入栈;
*     3.若该节点的左子树非空,将该节点的左子树入栈;
*结束
*
*说明一下:步骤2、3的次序不能颠倒,考虑到栈的特性,必须先入右子树
*/
void PreOrderNor(PBTNode pRoot)
{
	LinkStackNode S;
	LStackInit(&S); // 初始化一个栈
	LStackPush(&S, pRoot); // 将根节点入栈

	while (!IsLStackEmpty(&S)) // 当栈不为空
	{
		StackElementType ret_Pop = NULL;
		LStackPop(&S, &ret_Pop); // 栈顶元素出栈到ret_Pop
		printf("%c ", ret_Pop->_data); // 访问
		if (NULL != ret_Pop->_pRight)
		{
			// 右子树非空,入栈
			LStackPush(&S, ret_Pop->_pRight);
		}
		if (NULL != ret_Pop->_pLeft)
		{
			// 左子树非空,入栈
			LStackPush(&S, ret_Pop->_pLeft);
		}
	}
}

// 中序遍历递归 
void InOrder(PBTNode pRoot)
{
	if (NULL == pRoot)
	{
	// 递归出口
		return;
	}
	else
	{
		InOrder(pRoot->_pLeft);
		printf("%c ", pRoot->_data);
		InOrder(pRoot->_pRight);
	}
}

// 中序遍历二叉树
// 利用栈
/* 算法思想
*  从根节点开始,只要当前节点存在或者栈不为空,重复以下操作:
*    1、如果当前节点存在,入栈并遍历左子树
*    2、否则出栈并访问,然后遍历右子树
*/
void InOrderNor(PBTNode pRoot)
{
	LinkStackNode S;
	PBTNode p = NULL;

	LStackInit(&S); // 初始化一个栈
	p = pRoot;

	while (p != NULL || !IsLStackEmpty(&S))
	{
		if (p != NULL)
		{
			// 根指针进栈,遍历左子树
			LStackPush(&S, p);
			p = p->_pLeft;
		}
		else
		{
			// 根指针出栈,访问根节点,遍历右子树
			LStackPop(&S, &p);
			printf("%c ", p->_data);
			p = p->_pRight;
		}
	}
}

// 后续遍历递归 
void PostOrder(PBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return;
	}
	else
	{
		PostOrder(pRoot->_pLeft);
		PostOrder(pRoot->_pRight);
		printf("%c ", pRoot->_data);
	}
}

// 后序遍历非递归
/* 算法思想:
*  从根节点开始,只要当前节点存在或者栈不为空,重复以下操作:
*     1、从当前节点开始,进栈并遍历左子树直到左子树为空:
*     2、如果栈顶节点的右子树为空,或者栈顶节点的有孩子为
*        刚访问过的节点,出栈并访问,然后将当前节点指针置为空
*     3、否则遍历右子树
*  
*   值得一提的是,咱们需要标记一下刚刚访问过的节点
*/
void PostOrderNor(PBTNode pRoot)
{
	LinkStackNode S;
	LStackInit(&S); // 初始化一个栈

	PBTNode p = NULL;
	PBTNode q = NULL;

	p = pRoot;

	while (p != NULL || !IsLStackEmpty(&S))
	{
		if (p != NULL)
		{
			// 遍历左子树
			LStackPush(&S, p);
			p = p->_pLeft;
		}
		else
		{
			p = LStackTop(&S);
			if ((p->_pRight == NULL) || (p->_pRight == q))
			{
				// 无右孩子或右孩子遍历过
				printf("%c ", p->_data); // 访问根节点
				q = p; // 标记
				LStackPop(&S, &p);
				p = NULL;
			}
			else
				p = p->_pRight; // 遍历右子树
		}
	}
}

// 层序遍历 
// 利用队列
/* 算法思想:
*  初始化一个队列
*  将根节点指针入队列
*  队列非空时,循环执行以下步骤:
*      1、取队头元素并访问
*      2、若该节点的左子树非空,将该节点的左子树入队列
*      3、若该节点的右子树非空,将该节点的右子树入队列
*  结束
*  考虑队列“先进后出”的特性,刚好可以实现二叉树的层次遍历
*/
void LevelOrder(PBTNode pRoot)
{
	LinkQueue Q;
	LinkQueueInit(&Q); // 初始化一个对列

	LinkQueueEnter(&Q, pRoot); // 根节点入队
	
	while (!IsQunueEmpty(&Q))
	{

		QueueElementType _Head = NULL;
		// 取队头元素并访问
		LinkQueueDelete(&Q, &_Head);
		printf("%c ", _Head->_data);
		if (_Head->_pLeft != NULL)
		{
		// 左子树非空
			LinkQueueEnter(&Q, _Head->_pLeft);
		}
		if (_Head->_pRight != NULL)
		{
		// 右子树非空
			LinkQueueEnter(&Q, _Head->_pRight);
		}
	}
}

// 拷贝二叉树 采用递归思想
PBTNode CopyBinTree(PBTNode pRoot)
{
	if (pRoot == NULL)
	{
	// 递归出口
		return NULL;
	}
	else
	{
		PBTNode _new = BuyBinTreeNode(pRoot->_data);
		_new->_pLeft = CopyBinTree(pRoot->_pLeft);
		_new->_pRight = CopyBinTree(pRoot->_pRight);
		return _new;
	}
}

// 销毁二叉树 递归思想
// 和单链表一样,二叉树的销毁也不仅仅是把根销毁就行
// 同时考虑二叉树的特性,如果根已经被销毁,将无法访问根的左右孩子
// 所以只能采用后序的方法
void DestroyBinTree(PBTNode *pRoot)
{
	assert(pRoot);

	if (NULL == (*pRoot))
	{
		return;
	}
	else
	{
		DestroyBinTree(&(*pRoot)->_pLeft);
		DestroyBinTree(&(*pRoot)->_pRight);
		free(*pRoot);
		pRoot = NULL;
	}
}

// 交换函数
void _swap(PBTNode *left, PBTNode *right)
{
	PBTNode temp = *left;
	*left = *right;
	*right = temp;
}

// 二叉树的镜像递归  交换左右孩子的指针域
void MirrorBinTree(PBTNode pRoot)
{
	if (pRoot->_pLeft == NULL || pRoot->_pRight == NULL)
	{
		return;
	}
	_swap(&(pRoot->_pLeft), &(pRoot->_pRight));
	MirrorBinTree(pRoot->_pLeft);
	MirrorBinTree(pRoot->_pRight);
}

// 二叉树的镜像非递归 队列+循环
void MirrorBinTreeNor(PBTNode pRoot)
{
	LinkQueue Q;
	LinkQueueInit(&Q);

	LinkQueueEnter(&Q, pRoot);
	while (!IsQunueEmpty(&Q))
	{		
		QueueElementType ret = NULL;
		LinkQueueDelete(&Q, &ret);
		if (ret->_pLeft != NULL)
		{
			// 左子树不为空,入队
			LinkQueueEnter(&Q, ret->_pLeft);
		}
		if (ret->_pRight != NULL)
		{
			// 右子树不为空,入队
			LinkQueueEnter(&Q, ret->_pRight);
		}

		_swap(&(ret->_pLeft), &(ret->_pRight)); // 交换

	}
}

// 求二叉树中结点的个数 
// 递归 求左右子树的节点,相加
int BinTreeSize(PBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return 0;
	}
	return BinTreeSize(pRoot->_pLeft) + BinTreeSize(pRoot->_pRight) + 1;
}

// 获取二叉树中叶子结点的个数  递归
// 左右孩子都为空才是叶子节点 
int GetLeafCount(PBTNode pRoot)
{
	if (NULL == pRoot)
	{
		return 0;
	}
	if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
	{
		return 1;
	}
	return GetLeafCount(pRoot->_pLeft) + GetLeafCount(pRoot->_pRight);
}

// 求二叉树中K层结点的个数 
// 递归 求K-1层节点个数
// ...
// K == 1 return 1
int GetKLevelNode(PBTNode pRoot, int K)
{
	if (K == 1 && pRoot != NULL)
	{
		return 1;
	}
	if (K == 1 && pRoot == NULL)
	{
		return 0;
	}
	return GetKLevelNode(pRoot->_pLeft, K - 1) + GetKLevelNode(pRoot->_pRight, K - 1);
}

// 求二叉树的高度 递归
// 左、右子树高度的最大值 + 1
int Height(PBTNode pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}
	return 1 + (Height(pRoot->_pLeft) > Height(pRoot->_pRight) ? Height(pRoot->_pLeft) : Height(pRoot->_pRight));
}

// 采用层序遍历法查找二叉树中第一个值为data的元素  找到了返回1 没找到返回0
int Find(PBTNode pRoot, PBTNode* pos, BTDataType data)
{
	LinkQueue Q;
	LinkQueueInit(&Q); // 初始化队列

	LinkQueueEnter(&Q, pRoot); // 根节点入队

	while (!IsQunueEmpty(&Q))
	{
		// 队列非空
		QueueElementType _Head = NULL;
		LinkQueueDelete(&Q, &_Head);
		if (_Head->_data == data)
		{
		// 查看元素值是否为data
			(*pos) = _Head; // 利用参数带回节点地址
			return 1;
		}
		if (_Head->_pLeft != NULL)
		{
			// 遍历左子树
			LinkQueueEnter(&Q, _Head->_pLeft);
		}
		if (_Head->_pRight != NULL)
		{
			// 遍历右子树
			LinkQueueEnter(&Q, _Head->_pRight);
		}
	}

	return 0;
}

// 判断一个节点是否在一棵二叉树中  递归思想
int ISNodeInBTreeNode(PBTNode pRoot, PBTNode pos)
{
	if (NULL == pRoot || NULL == pos)
		return 0;
	if (pRoot->_data == pos->_data)
		return 1;
	if (ISNodeInBTreeNode(pRoot->_pLeft, pos) || ISNodeInBTreeNode(pRoot->_pRight, pos))
		return 1;

	return 0;
}

##测试
下面通过测试函数对以上操作进行测试
1.

void TestCreateBinTree_Order()
{
	BTDataType invalid = '#'; // 分隔符用来表示指针域为空
	PBTNode T = NULL; // 定义一颗二叉树的根
	const char* str= "ABD###CE##F";
	// 按照字符串创建一棵二叉树
	CreateBinTree(&T, str, strlen(str), invalid);
	
	// 先序递归遍历
	printf("PreOrder:");
	PreOrder(T);
	printf("\n");
	
	// 先序非递归遍历
	printf("PreOdNor:");
	PreOrderNor(T);
	printf("\n");
	
	// 中序递归遍历
	printf("InOrder:");
	InOrder(T);
	printf("\n");

	// 中序非递归遍历
	printf("InOdNor:");
	InOrderNor(T);
	printf("\n");

	// 后序递归遍历
	printf("PostOrder:");
	PostOrder(T);
	printf("\n");

	// 后序非递归遍历
	printf("PostOdNor:");
	PostOrderNor(T);
	printf("\n");

	// 层序遍历
	printf("LevelOrder: ");
	LevelOrder(T);
	printf("\n");

	DestroyBinTree(&Copy_T); // 销毁二叉树
}

// 主函数
int main()
{
	TestCreateBinTree_Order(); // 调用测试函数
	system("Pause");
	return 0;
}

测试结果:

这里写图片描述
2.测试二叉树拷贝函数

void TestCopyBinTree()
{
	BTDataType invalid = '#';
	PBTNode T = NULL;
	PBTNode Copy_T = NULL;
	const char* str = "ABD###CE##F";
	
	// 创建二叉树
	CreateBinTree(&T, str, strlen(str), invalid);
	
	// 前序遍历打印一次二叉树
	printf("PreOrder:");
	PreOrder(T);
	printf("\n");
	
	// 调用二叉树拷贝函数对T进行拷贝,存储在根节点为Copy_T的二叉树中
	Copy_T = CopyBinTree(T);
	
	// 前序遍历打印由T拷贝来的二叉树Copy_T
	printf("PreOrder:");
	PreOrder(Copy_T);
	printf("\n");

	DestroyBinTree(&Copy_T); // 销毁二叉树
	DestroyBinTree(&T); // 销毁二叉树

}

// 主函数
int main()
{
	TestCopyBinTree(); // 调用测试函数
	system("pause");
	return 0;
}

测试结果:
这里写图片描述
3.测试二叉树镜像操作的递归与非递归函数

void TestBTMirror_MirrorNor()
{
	BTDataType invalid = '#';
	PBTNode T = NULL;
	PBTNode Copy_T = NULL;
	const char* str = "ABD###CE##F";
	
	// 创建一棵二叉树
	CreateBinTree(&T, str, strlen(str), invalid);
	
	// 前序遍历打印二叉树
	printf("PreOrder:");
	PreOrder(T);
	printf("\n");
	
	// 先后掉用二叉树镜像函数
	MirrorBinTree(T);
	MirrorBinTreeNor(T);

	// 再次前序遍历打印二叉树
	printf("PreOrder:");
	PreOrder(T);
	printf("\n");
}

// 主函数
int main()
{
	TestBTMirror_MirrorNor(); // 调用测试函数
	system("pause");
	return 0;
}

测试结果:
这里写图片描述
4.求二叉树节点个数、求二叉树叶子节点个数、第K层节点个数

void TestBTSize_LeafCount_KLevelNode()
{
	BTDataType invalid = '#';
	PBTNode T = NULL;
	PBTNode Copy_T = NULL;
	const char* str = "ABD###CE##F";

	CreateBinTree(&T, str, strlen(str), invalid);

	printf("二叉树中节点的个数size = %d\n", BinTreeSize(T));
	printf("二叉树中叶子节点的个数count = %d\n", GetLeafCount(T));
	printf("二叉树中第%d层节点的个数Node = %d\n", 1, GetKLevelNode(T, 1));
	printf("二叉树的高度Height = %d\n", Height(T));
}

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

测试结果:
这里写图片描述

void TestFind_IsBTNode()
{
	BTDataType invalid = '#';
	PBTNode T = NULL;
	PBTNode ret_Find = NULL;
	BTDataType Find_char = 'D';
	int ret_IsInBTree = 0;
	const char* str = "ABD###CE##F";

	CreateBinTree(&T, str, strlen(str), invalid);

	// 用Find函数采用层序遍历的方法在二叉树中查找值为Find_char的第一次出现,并用ret_Find记录Find_char的位置
	Find(T, &ret_Find, Find_char);
	// 判断一个节点是否在二叉树中 结果是显然的,肯定在!!!
	ret_IsInBTree = ISNodeInBTreeNode(T, ret_Find);
	if (ret_IsInBTree == 0)
	{
		printf("不在!!!\n");
	}
	else
	{
		printf("在!!!\n");
	}

}

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

测试结果:
这里写图片描述

到此,二叉树的概念、基本操作以及测试就结束了
如有不正,欢迎指正!谢谢!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值