数据结构——二叉树

二叉树

1.二叉树树的定义:
二叉树是一种特殊的树结构,所有的节点度小于或等于2.
2.二叉树的5种基本形态:

  • 空二叉树
  • 只有一个根节点的二叉树
  • 只有左子树的二叉树、
  • 只有右子树的二叉树
  • 完全二叉数

3.两种特殊的二叉树:
满二叉树:所有的叶节点都在同一层上,若深度为k,则二叉树的节点为2的k次方减一。
完全二叉树:最后一层都存在节点或则右边缺少节点的树
4.二叉树的顺序存储:
对于一个完全二叉树,可以用一个一维数组进行存储,将二叉树按照自上而下,由左向右的顺序进行顺序存储。但对于一般的二叉树而言,就会浪费空间,因此,顺序存储适合完全二叉树。
5.二叉树的链式存储:
链式存储可以有不同的形式,如:二叉链表,三叉链表,双亲链表等,二叉链表最为常用。所以,一下就用二叉链表进行存储。

二叉树的链式存储:
二叉树上的每一个节点分为三个域组成,其中data域为存储的元素的值,lchild作为指针指向该节点的左孩子,rchild为该节点的右孩子节点。

typedef struct node{
	char data;
	struct node* lchild, * rchild;
}BinTNode,*BiTree;

6.二叉树的遍历:有二叉树的定义可知,每一棵非空子树有根节点(D),根节点的左子树(L),根节点的右子树®组成,因为每次先访问左子树在访问右子树所以自由三种不同的访问方式:DLR(先序遍历),LDR(中序遍历),LRD(后序遍历)。还有一种是按层次遍历是访问根节点,将根节点入队,然后,安顺序取出从队列中的一个节点,并按照其左右孩子节点先左后右分别入队,若队列为空则结束,否则继续执行。

//先序
void Preorder(BinTNode* T)
{
	if (T)
	{
		printf("%c", T->data);
		Preorder(T->lchild);
		Preorder(T->rchild);
	}
}
//中序 
void Inorder(BinTNode* T)
{
	if (T)
	{
		Inorder(T->lchild);
		printf("%c", T->data);
		Inorder(T->rchild);
	}
}
//后序 
void Postorder(BinTNode* T)
{
	if (T)
	{
		Postorder(T->lchild);
		Postorder(T->rchild);
		printf("%c", T->data);
	}
}
//层次遍历
void Leveorder(BinTNode* T)
{
	int front = 0, rear = 1;
	BinTNode* cq[Max], * p;
	cq[1] = T;
	while (front != rear)
	{
		front = (front + 1) % NodeNum;
		p = cq[front];           //出队 
		printf("%c", p->data);  //出队,输出 
		if (p->lchild != NULL)
		{
			rear = (rear + 1) % NodeNum;
			cq[rear] = p->lchild;  //左子树入队 
		}
		if (p->rchild != NULL)
		{
			rear = (rear + 1) % NodeNum;
			cq[rear] = p->rchild;  //右子树入队 
		}
	}
}

7.求二叉树的深度:

int TreeDepth(BinTNode* T)
{
	int hl, hr, max;
	if (T) 
	{
		hl = TreeDepth(T->lchild);
		hr = TreeDepth(T->rchild);
		max = hl > hr ? hl : hr;
		NodeNum = NodeNum + 1;
		if (hl == 0 && hr == 0)
			leaf = leaf + 1;
		return max + 1;
	}
	else
		return 0;
}

8.求叶子节点个数:

int countleaf(BinTNode* T)
{
	int hl, hr;
	if (T)
	{
		hl = countleaf(T->lchild);
		hr = countleaf(T->rchild);
		if (hl == 0 && hr == 0)  //若左右深度为0,即为叶子 
		{
			return 1;
		}
		else
			return hl + hr;
	}
	else
		return 0;
}

练习:建立一棵树,先后用先序,中序,后序,层次遍历输出,在求其深度和节点数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 30 //节点最大个数
typedef struct node {
	char data;
	struct node* lchild, * rchild;

}BinTNode;
int NodeNum, leaf;
BinTNode* CreatBinTree()
{
	BinTNode* T;
	char ch;
	if ((ch = getchar()) == '#')
	{
		return NULL;
	}
	else
	{
		T = (BinTNode*)malloc(sizeof(BinTNode));
		T->data = ch;
		T->lchild = CreatBinTree();
		T->rchild = CreatBinTree();
		return T;
	}
}
//先序 
void Preorder(BinTNode* T)
{
	if (T)
	{
		printf("%c", T->data);
		Preorder(T->lchild);
		Preorder(T->rchild);
	}
}
//中序 
void Inorder(BinTNode* T)
{
	if (T)
	{
		Inorder(T->lchild);
		printf("%c", T->data);
		Inorder(T->rchild);
	}
}
//后序 
void Postorder(BinTNode* T)
{
	if (T)
	{
		Postorder(T->lchild);
		Postorder(T->rchild);
		printf("%c", T->data);
	}
}
//求深度 
int TreeDepth(BinTNode* T)
{
	int hl, hr, max;
	if (T) 
	{
		hl = TreeDepth(T->lchild);
		hr = TreeDepth(T->rchild);
		max = hl > hr ? hl : hr;
		NodeNum = NodeNum + 1;
		if (hl == 0 && hr == 0)
			leaf = leaf + 1;
		return max + 1;
	}
	else
		return 0;
}
void Leveorder(BinTNode* T)
{
	int front = 0, rear = 1;
	BinTNode* cq[Max], * p;
	cq[1] = T;
	while (front != rear)
	{
		front = (front + 1) % NodeNum;
		p = cq[front];           //出队 
		printf("%c", p->data);  //出队,输出 
		if (p->lchild != NULL)
		{
			rear = (rear + 1) % NodeNum;
			cq[rear] = p->lchild;  //左子树入队 
		}
		if (p->rchild != NULL)
		{
			rear = (rear + 1) % NodeNum;
			cq[rear] = p->rchild;  //右子树入队 
		}
	}
}
int countleaf(BinTNode* T)
{
	int hl, hr;
	if (T)
	{
		hl = countleaf(T->lchild);
		hr = countleaf(T->rchild);
		if (hl == 0 && hr == 0)  //若左右深度为0,即为叶子 
		{
			return 1;
		}
		else
			return hl + hr;
	}
	else
		return 0;
}
int main()
{
	BinTNode* root;
	int i;
	int depth;
	printf("\n");
	printf("Creat Bin_Tree Input preorder:");//输入完全二叉树先序序列,#表示虚节点

	root = CreatBinTree(); //创建二叉树 
	do {
		printf("\t*********select**********\n");
		printf("\t1:Preorder Traversal\n");
		printf("\t2:Iorder Traversal\n");
		printf("\t3:Postorder Traversal\n");
		printf("\t4:PostTreeDepth,Node number,Leaf number\n");
		printf("\t5:Level Depth\n");//按层次遍历前,应先选择4,求出该树节点 
		printf("\t0:Exit\n");
		printf("\t*************************\n");
		getchar();
		scanf_s("%d", &i); //输入菜单号(0-5) 
		switch (i)
		{
		case 1:
			printf("Print Bin_tree Preorder:");
			Preorder(root);//先序遍历
			break;
		case 2:
			printf("Print Bin_tree Inorder:");
			Inorder(root);//先序遍历
			break;
		case 3:
			printf("Print Bin_tree Postorder:");
			Postorder(root);//先序遍历
			break;
		case 4:
			depth = TreeDepth(root);//求深度以及叶子数 
			printf("BinTree Depth=%d\nBinTree Node Number=%d\n:", depth, NodeNum);
			printf("BinTree Leaf number=%d", countleaf(root));
			break;
		case 5:
			printf("LevePrint Bin_Tree:");
			Leveorder(root);//按层次 
			break;
		case 0:
			exit(1);
		}
		printf("\n");
	} while (i != 0);
	system("pause");
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值