树和二叉树

1.树的概念及结构

1.1 基本概念

树是一种非线性的数据结构,它是由n个有限结点组成一个具有层次关系的集合。
在这里插入图片描述

  • 有一个特殊的结点,称为根结点,根结点没有前驱结点
  • 每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 树是递归定义的(根结点+子树)

1.2 树的存储表示

树有多种表示方式:如:双亲表示法,孩子表示法,孩子兄弟表示法等。常用孩子兄弟表示法

typedef int DataType;
struct Node
{
	struct Node* _fristchild1;   //第一个孩子结点
	struct Node* _pNextBrother;  //指向其下一个兄弟结点
	DataType _data;              //结点中的数据域
};

在这里插入图片描述

2.二叉树的概念及性质

2.1 概念

  • 一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别为左子树和右子树的二叉树组成。
  • 每个结点最多有两棵子树,即二叉树不存在度大于2的结点
  • 二叉树的子树有左右之分,其子树的次序不能颠倒

在这里插入图片描述

2.2 特殊的二叉树

1.满二叉树: 一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树。如果一个二叉树的层数为k,且结点总数是(2^k)-1,则它就是满二叉树。

2.完全二叉树: 对于深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称之为完全二叉树。(满二叉树是一种特殊的完全二叉树)
在这里插入图片描述

2.3 二叉树的存储结构

  • 顺序存储结构:使用数组来存储,最适用于存储完全二叉树。二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树。
  • 链式存储结构:用链表指示元素的逻辑关系。通常链表中每个结点由三个域组成,数据域和左右指针域。

2.4 二叉树的性质

1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h - 1.
3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
4. 具有n个结点的完全二叉树的深度h=Log2(n+1). (ps:Log2(n+1)是log以2为底,n+1为对数)
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对
于序号为i的结点有:
   若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
   若2i+1<n,左孩子序号:2i+12i+1>=n否则无左孩子
   若2i+2<n,右孩子序号:2i+22i+2>=n否则无右孩子
3.二叉树链式结构的实现

3.1 二叉树链式结构的遍历

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题.

  • NLR: 前序遍历(Preorder Traversal 亦称先序遍历): 根->左子树->右子树
  • LNR: 中序遍历(Inorder Traversal): 左子树->根->右子树
  • LRN:后序遍历(Postorder Traversal):左子树->右子树->根
  • 层序遍历:层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后自上而下,自左至右逐层访问树的结点的过程。

3.2 二叉树的基本操作实现(递归实现)

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

// 二叉树的初始化
void BinaryTreeInit(BTNode** root)
{
	assert(root);
	if (*root == NULL)
		return;
	*root = NULL;
	return;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* Index)
{
	BTNode* root;
	if (a[*Index] == '#')
		return NULL;

	root = (BTNode*)malloc(sizeof(BTNode));
	root->_data = a[*Index];

	++(*Index);
	root->_left = BinaryTreeCreate(a, Index);

	++(*Index);
	root->_right = BinaryTreeCreate(a, Index);

	return root;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
	if (*root)
	{
		BinaryTreeDestory((*root)->_left);
		BinaryTreeDestory((*root)->_right);
		free(*root);
		*root = NULL;
	}
}
// 二叉树结点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
// 二叉树叶子结点个数
// 二叉树叶子结点个数 = 左子树叶子结点个数 + 右子树叶子结点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->_left == NULL&&root->_right == NULL)
		return 1;
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
// 二叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
// 二叉树的高度
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;
	int leftheight = BinaryTreeHeight(root->_left) + 1;
	int rightheight = BinaryTreeHeight(root->_right) + 1;
	return rightheight > leftheight ? rightheight : leftheight;
}
// 求二叉树的镜像
// 递归的交换二叉树的左右子树
void BinaryTreeMirror(BTNode* root)
{
	if (root == NULL)
		return;
	BTNode* tmp = root->_left;
	root->_left = root->_right;
	root->_right = tmp;
	BinaryTreeMirror(root->_left);
	BinaryTreeMirror(root->_right);
	return;
}
// 二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	BTNode* ret;
	if (root == NULL)
	{
		return NULL;
	}
	//根节点
	if (root->_data == x)
	{
		return root;
	}
	//找左子树
	ret = BinaryTreeFind(root->_left, x);
	if (ret)
	{
		return ret;
	}
	//左子树找不到, 找右子树
	ret = BinaryTreeLeafSize(root->_right, x);
	if (ret)
	{
		return ret;
	}
	//没找到
	return NULL;
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
	if (root)
	{
		printf("%c ", root->_data);
		BinaryTreePrevOrder(root->_left);
		BinaryTreePrevOrder(root->_right);
	}
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root)
	{
		BinaryTreeInOrder(root->_left);
		printf("%c ", root->_data);
		BinaryTreeInOrder(root->_right);
	}
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root)
	{
		BinaryTreePostOrder(root->_left);
		BinaryTreePostOrder(root->_right);
		printf("%c ", root->_data);
	}
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root != NULL)
		QueuePush(&q, root);

	while (!QueueIsEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		printf("%c ", front->_data);
		QueuePop(&q);

		if (front->_left)
			QueuePush(&q, front->_left);
		if (front->_right)
			QueuePush(&q, front->_right);
	}
		printf("\n");
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root != NULL)
		QueuePush(&q, root);
	while (!QueueIsEmpty(&q))
	{
		BTNode* front = QueueFront(&qu);
		QueuePop(&q);
		if (front == NULL)
			break;
		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}
	while (!QueueIsEmpty(&q))
	{
		BTNode* front = QueueFront(&qu);
		QueuePop(&q);
		if(front != NULL)
		{
		    QueueDestroy(&q);
			return -1;
		}
	}
	return 0;
}

//测试
int main()
{
	char a[] = "ABD##E#H##CF##G##";
	int index = 0;
	BTNode* tree = BinaryTreeCreate(a, &index);
	
	printf("Size:%d\n", BinaryTreeSize(tree));
	printf("Leaf Size:%d\n", BinaryTreeLeafSize(tree));
	printf("K Level:%d\n", BinaryTreeLevelKSize(tree,3));
	printf("Height:%d\n", BinaryTreeHeight(tree));
	BinaryTreeLevelOrder(tree);
	printf("Tree Complete: %d\n",BinaryTreeComplete(tree));
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值