C语言 数据结构与算法---二叉树

一. 二叉树的性质

1. 满二叉树

在一棵二叉树上,如果所有分支结点都存在左子树和右子树,并且所有叶子都在一层上,这样的二叉树称为满二叉树

特点:

  • 叶子只能出现在最下一层,出现在其它层就不可能达到平衡
  • 非叶子结点的度一定为2
  • 在同样深度的二叉树中,满二叉树结点个数最多,叶子数最多

2. 完全二叉树

对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为 i 的结点在二叉树中的位置完全相同,则称这棵二叉树为完全二叉树

特点:

  • 叶子节点只能出现在最下两层
  • 最下层的叶子一定集中在左部连续位置
  • 倒数两层,若有叶子结点,一定都在右部连续位置
  • 如果结点度为 1 ,则该结点只有左孩子,即不存在只有右子树的情况
  • 同样结点的二叉树,完全二叉树深度最小

3. 二叉树的性质

  1. 在二叉树的第i(i>=1)层最多有2^(i - 1)个结点。
  2. 深度为k(k>=0)的二叉树最少有k个结点,最多有2^k-1个结点。
  3. 对于任一棵非空二叉树,若其叶结点数为n0,度为2的非叶结点数为n2,则n0 = n2 +1
  4. 具有n个结点的完全二叉树的深度为int_UP(log(2,n+1))
  5. 如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,3,......,n,然后按此结点编号将树中各结点顺序的存放于一个一维数组,并简称编号为i的结点为结点i( i>=1 && i<=n),则有以下关系:
    (1)若 i= 1,则结点 i 为根,无父结点;若 i> 1,则结点 i 的父结点为结点int_DOWN(i / 2);
    (2)若 2*i <= n,则结点 i 的左子女为结点2*i
    (3)若2*i<=n,则结点i的右子女为结点2*i+1
    (4)若结点编号i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟为结点i-1
    (5)若结点编号i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1
    (6)结点i所在的层次为int_DOWN(log(2,i))+1

二. 二叉链表

1. 二叉树的结构

typedef char TElemType;

typedef struct BiTNode
{
	TElemType data;
	struct BiTNode* lchild, * rchild;  //左右孩子指针
}BiTNode,*BiTree;

2. 二叉树的遍历

采用函数递归的思想

前序遍历:
若二叉树为空,则空操作返回,
否则: 根结点->左子树->右子树

void Preorder(BiTree T)
{
	if (T == NULL)
	{
		return;
	}

	printf("%c",T->data);
	Preorder(T->lchild);
	Preorder(T->rchild);
}

中序遍历:
若二叉树为空,则空操作返回,
否则:左子树->根结点->右子树

void Inorder(BiTree T)
{
	if (T == NULL)
	{
		return;
	}

	Inorder(T->lchild);
	printf("%c",T->data);
	Inorder(T->rchild);
}

后序遍历:
若二叉树为空,则空操作返回,
否则:左子树->右子树->根结点

void Postorder(BiTree T)
{
	if (T == NULL)
	{
		return;
	}

	Postorder(T->lchild);
	Postorder(T->rchild);
	printf("%c", T->data);
}

3. 二叉树的建立

为了确定每个结点是否有左右孩子,我们将二叉树中每个结点的空指针引出一个虚结点,其值为一特定值如 “#”

//按前序输入
void CreatBiTree(BiTree *T) //二级指针
{
	TElemType ch;
	scanf("%c",&ch);
	if (ch == '#')
	{
		*T = NULL;
	}
	else
	{
		*T = (BiTree)malloc(sizeof(BiTNode));
		if (!*T)
		{
			return;
		}

		(*T)->data = ch; //生成根结点
		CreatBiTree(&(*T)->lchild);//构造左子树
		CreatBiTree(&(*T)->rchild);//构造右子树
	}
}

利用字符串建立二叉树:

//T:二级指针;  str:传入的字符串;  n:当前字符串的位数
int CreatBiTree2(BiTree* T,char *str,int n)
{
	char ch = str[n];
	n++;
	if (str[n] != '\0')  //字符串末尾
	{
		if (ch == '#')
		{
			*T = NULL;
		}
		else
		{
			*T = (BiTree)malloc(sizeof(BiTree));
			if (!*T)
			{
				return;
			}

			(*T)->data = ch; //生成根结点
			n = CreatBiTree2(&(*T)->lchild,str,n);//构造左子树
			n = CreatBiTree2(&(*T)->rchild,str,n);//构造右子树
		}
	}
	return n;
}

若要按照后序或中序输入,只需调整构造根结点与左右子树的顺序即可

4. 求二叉树叶子结点

int num = 0;
void CalculateTree(BiTree T)
{
	if(!T)
	{
		return ;
	}
	//若为叶子
	if(!T->lchild && !T->rchild)
	{
		num++;
	}
	//左子树叶子结点数目
	CalculateTree(T->lchild);
	//右子树叶子结点数目
	CalculateTree(T->rchild);	
}

5. 求二叉树的高度

int CaculateTreDepth(BiTree T){

if(T == NULL)
{
	return 0;
}

int depth = 0;
int leftDepth = CaculateTreDepth(root->lchild);
int rightDepth = CaculateTreDepth(root->rchild);
depth = leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;

return depth;
}
发布了37 篇原创文章 · 获赞 30 · 访问量 1120

猜你喜欢

转载自blog.csdn.net/myjess/article/details/104511791