数据结构初阶之二叉树(3)

目录

链式二叉树的结构

二叉树的遍历

二叉树遍历的作用

前序遍历

前序遍历思路

前序遍历实现

中序遍历

中序遍历思路

中序遍历实现

后续遍历

后序遍历思路

后序遍历实现

实际递归问题

二叉树的节点个数

二叉树叶节点个数

二叉树的高度

第K层节点个数

返回x所在的节点


链式二叉树的结构

二叉树的结构多种多样,顺序结构的二叉树只适合完全二叉树,非完全二叉树在顺序结构中会浪费空间,如下:

数据结构初阶之二叉树(3)_第1张图片当二叉树中非末位节点没有数据时,就会浪费空间,所以非完全二叉树不适合顺序结构,更适合链式结构,那么链式结构的节点是怎么定义的呢?

数据结构初阶之二叉树(3)_第2张图片

 如上图,链式结构中根节点定义两个指针分别指向子节点。

typedef int BinaryTreeDataType;

typedef struct BinaryTreeNode
{
	BinaryTreeDataType val;
	struct BinaryTreeNode * left;
	struct BinaryTreeNode * right;
}BTNode;

二叉树的遍历

二叉树遍历的作用

二叉树的遍历是二叉搜索树的基础。

前序遍历

前序遍历思路

前序遍历是先访问根节点,再访问左子节点和右子节点。

数据结构初阶之二叉树(3)_第3张图片

数据结构初阶之二叉树(3)_第4张图片

对于二叉树的遍历,使用递归更方便,上图中可以将整个二叉树分化成只包含根节点,左子节点和右子节点的集合。对每一个节点只需要访问其数据之后,先调用左节点,再调用右节点,最终调用的顺序如下:

数据结构初阶之二叉树(3)_第5张图片前序遍历实现

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

	printf("%d ", root->val);

	preOrder(root->left);
	preOrder(root->right);
}

中序遍历

中序遍历思路

中序遍历的访问顺序是左节点,根节点,右节点。

数据结构初阶之二叉树(3)_第6张图片

中序遍历一定从最左边的节点开始访问,然后是根节点,右节点,最终调用顺序如下:

 数据结构初阶之二叉树(3)_第7张图片

中序遍历实现

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

	InOrder(root->left);
	printf("%d ", root->val);
	InOrder(root->right);
}

后续遍历

后序遍历思路

 后序遍历的顺序是,左子节点->右子节点->根节点:

数据结构初阶之二叉树(3)_第8张图片

后序遍历实现

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

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->val);
}

实际递归问题

二叉树的节点个数

分析一:遍历全部节点非空节点用全局变量计数,全局变量可以重新赋值,但是需要在调用函数前进行重新赋值,但是这样的方法需要每次使用重新赋值,同时全局变量容易被修改,并不安全。

int count = 0;

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

	++count;
	BTreeSize(root->left);
	BTreeSize(root->right);
}


int main()
{
	BTNode * n1 = crearBinaryTree();
	count = 0;
	BTreeSize(n1);
	printf("%d\n", count);
	count = 0;
	BTreeSize(n1);
	printf("%d\n", count);
	count = 0;
	BTreeSize(n1);
	printf("%d\n", count);
	count = 0;
	BTreeSize(n1);
	printf("%d\n", count);
	count = 0;
	BTreeSize(n1);
	printf("%d\n", count);
	system("pause");
	return 0;
}

 分析二:分治法,就是把一个复杂的问题分化成若干个类型相同的小问题。

数据结构初阶之二叉树(3)_第9张图片

 分治法实现:

int BTreeSize(BTNode*root)
{
	if (root == NULL)
	{
		return 0;
	}

	return  BTreeSize(root->left)  + BTreeSize(root->right) + 1;
}

二叉树叶节点个数

分析:二叉树中没有子树的节点就是叶子节点,求二叉树叶子节点个数就是求没有左子树与右子树的根节点的个数。

二叉树中如果根节点是叶节点返回1,整个二叉树的叶节点由左子树的叶节点加上右子树的叶节点组成。

实现:

int BTreeLeaSize(BTNode*root)
{
	if (root == NULL)
	{
		return 0;
	}

	if (root->left == NULL&&root->right == NULL)
	{
		return 1;
	}

	return BTreeLeaSize(root->left) + BTreeLeaSize(root->right);
}

二叉树的高度

分析:求取二叉树的高度,本质是左子树与右子树的高度进行比较,大于的一方加根节点的层数再返回。

代码实现:

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

第K层节点个数

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

返回x所在的节点

BTNode * SearchX(BTNode * root, BinaryTreeDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->val == x)
	{
		return root;
	}
	BTNode * left = SearchX(root->left, x);
	if (left)
	{
		return left;
	}
	BTNode * right = SearchX(root->right, x);
	if (right)
	{
		return right;
	}

	return NULL;
	
}

你可能感兴趣的:(数据结构初阶,数据结构,算法,c语言,链表,开发语言)