二叉树的实现

一、引言       

        二叉树一般可以用两种结构存储,一种是顺序表,另一种是链表,一般来说,如果是完全二叉树可以采用顺序表储存的方式,但如果不是完全二叉树,就会造成空间的浪费。

        因此,我们采用二叉树的链式储存结构。这里介绍二叉链。

二、具体实现

(1)二叉树的结构

typedef int BTDataType;

// 二叉链
typedef struct BinaryTreeNode
{
 struct BinTreeNode* left; // 指向当前结点左孩子
 struct BinTreeNode* right; // 指向当前结点右孩子
 BTDataType data; // 当前结点值域
}BTNode;

        这一段程序定义了节点左右孩子的指向和当前节点存储的值,并重命名为BTNode便于后续操作。

(2)二叉树的前序遍历

        二叉树的前序遍历代表我们按照“根、左子树、右子树”的顺序进行访问,代码如下:

void BTPrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	
	printf("%d ", root->data);
	BTPrevOrder(root->left);
	BTPrevOrder(root->right);
}

        我们以一棵二叉树为例,看看是如何进行前序访问的:

(3)二叉树的中序遍历

        与前序遍历整体上相差无几,只需要将打印的语句移到中间即可

void BTInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BTInOrder(root->left);
	printf("%d ", root->data);
	BTInOrder(root->right);
}

(4)二叉树的后序遍历

        后序遍历也是如此,将打印语句移到最后即可

void BTPostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BTPostOrder(root->left);
	BTPostOrder(root->right);
	printf("%d ", root->data);
}

(5)二叉树的创建(前序遍历来创建)

        了解了前序遍历后,我们就可以利用这些遍历方法来创建二叉树。我们在键盘中键入字符串例如“1 2 # 8 # # 4 9 # # #”代表我们需要创建的二叉树,其中1 2 4……代表节点的值域,#代表NULL,代码如下:

BTNode* BTCreate(BTDataType* a, int* pi)//二叉树创建
{
	if (a[(*pi)] == '#')
	{
		(*pi)++;
		return NULL;
	}

	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	root->data = a[(*pi)++];
	root->left = CreateTree(a, pi);
	root->right = CreateTree(a, pi);

	return root;
}

(6)二叉树的销毁

        在销毁二叉树时,我们一般采用后序销毁的办法,即先销毁左右子树,最后销毁根几点

        

void BTDestroy(BTNode* root)
{
	if (root == NULL)
		return;
	BTDestroy(root->left);
	BTDestroy(root->right);
	free(root);
	root = NULL;
}

(7)二叉树的叶子个数

        在二叉树中,我们想找到二叉树的所有叶子节点,采用递归遍历的方式

int TreeLeaveSize(BTNode* root)
{
    if(root == NULL)
        return 0;
    else if(root->left == NULL && root->right == NULL)
        return 1;
    return TreeLeaveSize(root->left) + TreeLeaveSize(root->right);
}

(8)二叉树总节点个数

        如果该节点不为0,就返回1并继续递归遍历该节点的左子树和右子树

int BTSize(BTNode* root)
{
	return root == NULL ? 0 : BTSize(root->left) + BTSize(root->right) + 1;
}

(9)二叉树第k层节点个数

        这段程序本质上依旧采用递归的思想,我们都知道,当k为1时,不管何种二叉树(只要不是空二叉树),在这一层永远只有1个根节点,因此通过这种思想,我们在从根节点向下遍历k层时,每经过一层,k就减1,当k=1的时候,返回1。

int BTLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;
	else if (k == 1)
		return 1;
	else
		return BTLevelKSize(root->left, k - 1) + BTLevelKSize(root->right, k - 1);
}

(10)二叉树高度

        二叉树的高度是取左右子树中高的那一个的高度再加一,同样采用递归的方法

	if (root == NULL)
		return 0;

	int high1 = BTHeight(root->left);
	int high2 = BTHeight(root->right);

	return (high1 > high2) ? high1 + 1 : high2 + 1;

        需要注意的是,在这段程序中我们引入high1,high2变量来储存我们计算的值,否则每次递归时程序都将重新计算上一层的高度,会导致运算量成倍增长

(11)查找值为x的节点

BTNode* BTFind(BTNode* root, BTDataType x)
{
	if (root->data = x)
		return root;
	if (root == NULL)
		return NULL;
	BTNode* left = BTFind(root->left, x);
	if (left)
	{
		return left;
	}
	return  BTFind(root->right, x);
}

        这段程序中,我们先查找左子树,如果没有,再继续查找右子树,直到全部为空,进行返回。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值