二叉树的遍历

二叉树的递归遍历

  • 先序遍历

    • 先跟
    • 再左
    • 再右
  • 中序遍历

    • 先左
    • 再根
    • 再右
  • 后序遍历

    • 先左
    • 再右
    • 再根
  • 需要遍历的树
    请添加图片描述

  • 先序遍历结果: A B C D E F G H

  • 中序遍历结果: B D C E A F H G

  • 后续遍历结果: D E C B H G F A

递归遍历实现代码

// 二叉树节点
struct BinaryNode
{
	char* ch;// 显示的字母
	struct BinaryNode* lChild; // 左孩子
	struct BinaryNode* rChild; // 右孩子
};

// 递归函数 实现遍历
void recursion(struct BinaryNode* root)
{
	if (root == NULL)
	{
		return;
	}

	// 根
	printf("%c\n", root->ch);
	// 左
	recursion(root->lChild);
	// 右
	recursion(root->rChild);
}

void test01()
{
	// 创建节点
	struct BinaryNode nodeA = { 'A', NULL, NULL };
	struct BinaryNode nodeB = { 'B', NULL, NULL };
	struct BinaryNode nodeC = { 'C', NULL, NULL };
	struct BinaryNode nodeD = { 'D', NULL, NULL };
	struct BinaryNode nodeE = { 'E', NULL, NULL };
	struct BinaryNode nodeF = { 'F', NULL, NULL };
	struct BinaryNode nodeG = { 'G', NULL, NULL };
	struct BinaryNode nodeH = { 'H', NULL, NULL };

	// 建立节点之间的关系
	nodeA.lChild = &nodeB;
	nodeA.rChild = &nodeF;

	nodeB.lChild = NULL;
	nodeB.rChild = &nodeC;

	nodeC.lChild = &nodeD;
	nodeC.rChild = &nodeE;

	nodeF.lChild = NULL;
	nodeF.rChild = &nodeG;

	nodeG.lChild = &nodeH;
	nodeG.rChild = NULL;

	// 通过递归函数实现先序遍历
	recursion(&nodeA);
}

二叉树的常规编程

求二叉树叶子数量

  • 利用递归特性统计
  • 节点左子树 和 右子树 同时是NULL, 认定为叶子

代码实现

void calculateLeafNum(struct BinaryNode* root, int* num)
{
	if (root == NULL)
	{
		return;
	}

	if (root->lChild == NULL && root->rChild == NULL)
	{
		(*num)++;
		return;
	}


	calculateLeafNum(root->lChild, num);
	calculateLeafNum(root->rChild, num);
}

求二叉树的高度

  • 利用递归特性统计
  • 左子树 和 右子树高度相比 取大的值 +1 就是树的高度

代码实现

// 统计树的高度
int getTreeHeight(struct BinaryNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	// 获取左子树的高度
	int lHeight = getTreeHeight(root->lChild);

	// 获取右子树的高度
	int rHeight = getTreeHeight(root->rChild);

	// 取大的值+ 1 就是树的高度
	int height = lHeight > rHeight ? lHeight + 1 : rHeight + 1;

	return height;
}

拷贝二叉树

  • 利用递归特性
  • 先拷贝左子树
  • 再拷贝右子树
  • 创建新节点
  • 将左子树 右子树 挂在新节点上
  • 返回新节点

实现代码

// 拷贝二叉树
struct BinaryNode* copyTree(struct BinaryNode* root)
{
	if (root == NULL)
	{
		return NULL;
	}

	// 先拷贝左子树
	struct BinaryNode* lChild = copyTree(root->lChild);

	// 再拷贝右子树
	struct BinaryNode* rChild = copyTree(root->rChild);

	// 创建新节点
	struct BinaryNode* newNode = malloc(sizeof(struct BinaryNode));
	newNode->lChild = lChild;
	newNode->rChild = rChild;
	newNode->ch = root->ch;

	// 返回结果
	return newNode;
}

释放二叉树

  • 利用递归特性
  • 先释放左子树
  • 再释放右子树
  • 再释放根节点

实现代码

// 释放新树
void freeTree(struct BinaryNode* root)
{
	if (root == NULL)
	{
		return;
	}
	// 先释放左子树
	freeTree(root->lChild);
	// 再释放右子树
	freeTree(root->rChild);
	
	printf("%c 被释放了\n", root->ch);
	// 最后释放根节点
	free(root);
}

二叉树的非递归遍历

  • 将根节点压入栈中
  • 进入循环: 只要栈中元素大于0, 进行循环操作
    • 弹出栈顶元素
    • 如果这个栈元素为真
      • 输出这个元素, 且执行下一次循环
    • 如果栈顶元素为假
      • 将节点的标志设为真
      • 将该节点的右子树, 左子树, 根 压入栈中
      • 执行下一次循环

设计

  • 将每个节点元素多加一个标志位, 默认标志位都为假
struct BinaryNode
{
	char* ch;// 显示的字母
	struct BinaryNode* lChild; // 左孩子
	struct BinaryNode* rChild; // 右孩子
	int flag; // 节点标志
};

代码实现

// 非递归遍历
void nonRecursion(struct BinaryNode* root)
{
	// 创建栈
	SeqStack myStack = init_SeqStack();

	// 将根节点压入栈中
	push_SeqStack(myStack, root);

	// 只要栈中元素大于0, 进行循环操作
	while (size_SeqStack(myStack) > 0)
	{
		// 获取栈顶元素
		struct BinaryNode* topNode = top_SeqStack(myStack);

		// 弹出栈顶元素
		pop_SeqStack(myStack);


		if (topNode->flag == 1)
		{
			// 栈元素为真
			// 输出这个元素
			printf("%c\n", topNode->ch);
			// 执行下一次循环
			continue;
		}

		// 如果栈顶元素为假
		// 将节点的标志设为真
		topNode->flag = 1;

		// 将该节点的右子树, 左子树, 根 压入栈中
		if (topNode->rChild != NULL)
		{
			push_SeqStack(myStack, topNode->rChild);
		}

		if (topNode->lChild != NULL)
		{
			push_SeqStack(myStack, topNode->lChild);
		}

		push_SeqStack(myStack,topNode);
	}
	
	// 销毁栈
	destroy_SeqStack(myStack);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值