二叉树基本操作实现

链式二叉树

数组表示二叉树要求二叉树必须是完全二叉树或者是满二叉树,所以二叉树还可以用链式表示其结构代码如下:

typedef int DataType;
typedef struct BinaryTree{
        struct BinaryTree* _left;
        struct BinaryTree* _right;
        DataType data;
};BTNode
前序遍历

前序遍历的顺序为根,左子树,右子树,所以也被称为先根遍历。

如图以这个二叉树为例:

在这里插入图片描述

这个二叉树以前序遍历的顺序为:2->3->6->4->9->7

在这里插入图片描述

实际上我们遍历时需要遍历到每个结点的空为止:

在这里插入图片描述

中序遍历

中序遍历的顺序为左子树,根,右子树,所以中序遍历也叫做中根遍历

在这里插入图片描述

继续以此图为例,中序遍历的顺序为:6->3->2->9->4->7

实际的遍历顺序为

在这里插入图片描述

后序遍历

后序遍历的顺序为左子树,右子树,根,所以后序遍历也叫做后根遍历

在这里插入图片描述

后序遍历的顺序为:6->3->9->7->4->2

实际的遍历顺序为:

在这里插入图片描述

二叉树的遍历代码可以用递归思想或者迭代思想,这里先采用递归的思想实现代码。

void PreOrder(BTNode* root);
//前序遍历
void InOrder(BTNode* root);
//中序遍历
void PostOrder(BTNode* root);
//后序遍历
void PreOrder(BTNode* root) {
	if (root == NULL) {
	/*	printf("NULL ");*/
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->_left);
	PreOrder(root->_right);
}
//前序遍历

输入一个这样的树

在这里插入图片描述

在这里插入图片描述

void InOrder(BTNode* root) {
	if (root == NULL) {
		return;
	}
    InOrder(root->_left);
	printf("%d ", root->_left); 
    InOrder(root->_right);
}
//中序遍历

结果:

在这里插入图片描述

void PostOrder(BTNode* root) {
	if (root == NULL) {
		return;
	}

	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%d ", root->data);
}
//后序遍历

结果:

在这里插入图片描述

层序遍历

二叉树的层序遍历可以借助数据结构中的队列,利用队列先进先出的特点达成层序遍历的要求。

首先先进入根节点,然后将根节点的左孩子和右孩子依次进队,然后每次出一个结点,然后再将该结点的左孩子和右孩子依次进队。

代码:

void BTreeLevelOrder(BTNode* root) {
	Queue q;
	
	QueueInit(&q);//初始化队列
	
	if (root) {
		QueuePush(&q, root);
	}//根节点入队

	while (!QueueEmpty(&q)) {//队列中不为空时,出对头结点然后加入该结点的左右孩子
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		printf("%d ", front->data);

		if (front->_left) {
			QueuePush(&q, front->_left);
		}

		if (front->_right) {
			QueuePush(&q, front->_right);
		}
	}

	QueueDestory(&q);
	printf("\n");

}

结果:

在这里插入图片描述

求二叉树的结点个数

这个二叉树的结点个数很明显可以看出是6,代码实现如下;

int BTreeSize(BTNode* root) {
	return root == NULL ? 0 : BTreeSize(root->_left) + BTreeSize(root->_right) + 1;
}
//求二叉树结点个数

这段代码采用分治的思想,将问题一个一个减小,求二叉树的结点个数就是求其左子树和其右子树结点个数之和再加上自己,通过调用自己的左子树和右子树将问题分成两部分然后进行重复递归。

结果:

在这里插入图片描述

求最大深度

如何求最大深度我们可以这样思考,每一次调用自己的左子树和右子树,然后将两者的深度进行比较哪个大返回哪个。

代码如下:

int BTreeDepth(BTNode* root) {
	if (root == NULL) {
		return 0;
	}
	int LeftDepth = BTreeDepth(root->_left);
	int RightDepth = BTreeDepth(root->_right);
	return LeftDepth > RightDepth ? LeftDepth + 1 : RightDepth + 1;
}

结果:在这里插入图片描述

求叶子结点个数

叶子结点是没有孩子的结点,从这一条件入手,采用分治的思想,求整个树的叶子结点个数就是求左子树叶子结点个数加上右子树叶子结点个数。

代码:

int BTreeLeafSize(BTNode* root) {
    if (root == NULL) {
        return 0;
    }
    
    if (root->_left == NULL && root->_right == NULL) {
        return 1;
    }
    return BTreeLeafSize(root->_left) + BTreeLeafSize(root->_right);
}

结果:

在这里插入图片描述

二叉树第K层的结点数量

对于第K层结点数量也就相当于根结点的下一层结点的K-1层结点,用此思路就可以进行递归调用,走到结果一层时返回1,最终得出第K层结点的数量。

int BTreeKLevelSize(BTNode* root, int k) {
    assert(k > 1);
    if (root == NULL) {
        return 0;
    } 
    if (k = 1) {
        return 1;
    }
     
    return BTreeKLevelSize(root->_left, k - 1) + BTreeKLevelSize(root->_right, k - 1);
}

结果:

在这里插入图片描述

以值查找二叉树结点

按值进行查找,如果结点为空就返回空,如果找到该结点就返回该结点,然后再递归调用自己的左孩子和有孩子。

BTNode* BTreeFind(BTNode* root, BTDataType k) {
	if (root == NULL) {
		return NULL;
	}

	if (root->data == k) {
		return root;
	}

	BTNode* ret1 = BTreeFind(root->_left, k);
	if (ret1) {
		return ret1;
	}

	BTNode* ret2 = BTreeFind(root->_right, k);
	if (ret2) {
		return ret2;
	}
}

判断是否为完全二叉树

对于一个完全二叉树我们要求其最后一层结点必须是由左向右,并且前n-1层必须是满节点。

所以我们可以继续采用层序遍历的思想,当我们遍历到空结点时,如果下一个结点不为空,则说明该层有空缺,不是依次向右或者说前n-1层结点不满。

代码:

bool BTreeComplete(BTNode* root) {
	Queue q;
	QueueInit(&q);

	if (root) {
		QueuePush(&q, root);
	}
	
	while (!QueueEmpty(&q)) {
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front == NULL) {
			break;
		}//遇到空时我们就break检查其后结点是否为空
		
		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}//层序遍历思想

	while (!QueueEmpty(&q)) {
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front) {
			return false;
		}//如果后面的结点存在说明不是完全二叉树
	}

	return true;
}

结果:

在这里插入图片描述

以上就是二叉树的基本操作,如果要继续加深练习可以选择OJ题进行练习
二叉树的中序遍历 二叉树的前序遍历 二叉树的后序遍历 对称二叉树 二叉树的最大深度 翻转二叉树 另一棵树的子树 单值二叉树

  • 2
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
二叉树是一种非常重要的数据结构,它的基本操作包括创建、销毁、遍历、查找等。下面是二叉树基本操作实现方法: 1. 创建二叉树:通过前序遍历的数组构建二叉树,其中 '#' 表示空节点。具体实现方法可以参考引用中的 BinaryTreeCreate 函数。 2. 销毁二叉树:遍历二叉树,依次释放每个节点的内存空间。具体实现方法可以参考引用中的 BinaryTreeDestory 函数。 3. 遍历二叉树二叉树的遍历包括前序遍历、中序遍历、后序遍历和层序遍历。具体实现方法可以参考引用中的 BinaryTreePrevOrder、BinaryTreeInOrder、BinaryTreePostOrder 和 BinaryTreeLevelOrder 函数。 4. 查找二叉树节点:在二叉树中查找值为 x 的节点,具体实现方法可以参考引用中的 BinaryTreeFind 函数。 5. 计算二叉树节点个数:计算二叉树中节点的个数,具体实现方法可以参考引用[2]中的 BinaryTreeSize 函数。 6. 计算二叉树叶子节点个数:计算二叉树中叶子节点的个数,具体实现方法可以参考引用中的 BinaryTreeLeafSize 函数。 7. 计算二叉树第 k 层节点个数:计算二叉树中第 k 层节点的个数,具体实现方法可以参考引用中的 BinaryTreeLevelKSize 函数。 8. 判断二叉树是否是完全二叉树:判断二叉树是否是完全二叉树,具体实现方法可以参考引用中的 BinaryTreeComplete 函数。 9. 计算二叉树的深度:计算二叉树的深度,具体实现方法可以参考引用中的 BinaryTreeDeep 函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值