二叉树

匿名 (未验证) 提交于 2019-12-03 00:26:01

【基本概念】

二叉树( binary tree)是一种特殊的树型结构,它是度数为2的树,即二叉树的每个结点最多有两个子结点。

每个结点的子结点分别称为左孩子、右孩子,它的两棵子树分别称为左子树、右子树。

二叉树有5种基本形态:


【二叉树的性质】

1.在二叉树的第 i 层上最多有 2^(i-1) 个结点(i>=1)

满二叉树,其特点是每层上的结点数都是最大结点数。

对满二叉树的结点进行连续编号,约定编号从根结点起,自上而下,从左到右,由此引出完全二叉树的定义:深度为 k,有 n 个结点的二叉树当且仅当其每一个结点都与深度为 k 的满二叉树中编号从 1 到 n 的结点一一对应时,称为完全二叉树


3.对任意一棵二叉树,如果其叶结点数为 n0,度为 2 的结点数为 n2,则一定满足:n0=n2+1

4.具有 n 个结点的完全二叉树的深度为 floor(log2n)+1

5.对于一棵具有 n 个结点的完全二叉树,对任一个结点(编号为i),有:

【二叉树的存储结构】

方法1:链式存储结构,即:单链表结构或双链表结构

typedef struct node; typedef node *tree; struct node{     char data;  tree lchild, rchild; }; tree bt;  或  typedef struct node; typedef node *tree; struct node{     char data;  tree lchild, rchild,father; }; tree bt;

如图,一棵二叉树(左图)即可用单链表表示(右图)



方法2:顺序存储结构,即:用几个数组与一个指针变量表示

const int n = 10; char data[n]; char lchild[n]; char rchild[n]; int root;

表达式树(用叶结点表示运算元,分支结点表示运算符)经常用到此种方式。

例:现有一表达式:(a+b/c)*(d-e),可用下图表示


数据结构定义如下:

按表达式的书写顺序逐个编号,分别为1..9,注意表达式中的所有括号在树中是不出现的,因为表达式树本身就是有序的,叶结点的左右子树均为空(用0表示)。

char data[9] = {'a', '+', 'b', '/', 'c', '*', 'd', '-', 'e'}; int lchild[9] = {0,1,0,3,0,2,0,7,0}; int rchild[9] = {0,4,0,5,0,8,0,9,0}; int root=6; //根结点指针,初值指向'*'

【二叉树的基本操作】

1.遍历二叉树

二叉树的遍历:按一定的规律和次序访问树中的各个结点,而且每个结点仅被访问一次。

二叉树的遍历问题:在树中查找具有某种特征的结点,或对所有结点逐一进行某种处理。

遍历一般按照从左到右的顺序,分为三种方法:先序遍历、中序遍历、后序遍历

注:已知先序序列和中序序列可以确定出二叉树,已知中序序列和后序序列也可以确定出二叉树

1)先序遍历

若二叉树为空,则空操作,否则:先访问根结点,再先序遍历左子树,然后先序遍历右子树

void preorder(tree bt)//先序遍历根结点为bt的二叉树的递归算法 {     if(bt)    {       cout << bt->data;       preorder(bt->lchild);       preorder(bt->rchild);    } }

以下图为例,先序遍历此图结果为:124753689


2)中序遍历

若二叉树为空,则空操作,否则:先中序遍历左子树,再访问根结点,然后中序遍历右子树

void inorder(tree bt)//中序遍历根结点为bt的二叉树的递归算法 { 	if(bt)  {   inorder(bt->lchild);   cout << bt->data;   inorder(bt->rchild);   } }

以下图为例,中序遍历此图结果为:742513869



3)后序遍历

若二叉树为空,则空操作,否则:先后序遍历左子树,再后序遍历右子树,然后访问根结点

void postorder(tree bt)  //后序遍历根结点为bt的二叉树的递归算法 {     if(bt)     {         postorder(bt->lchild);   	    postorder(bt->rchild);  	    cout << bt->data;     } }

以下图为例,后序遍历此图结果为:745289631



2.建立二叉树

void pre_crt(tree &bt)//按先序次序输入二叉树中结点的值,生成 { 	char ch; 	ch = getchar();//二叉树的单链表存储结构,bt为指向根结点的指针,'$'表示空树  	if(ch != '$') 	{ 		bt = new node;//建根结点 		bt->data = ch; 		pre_crt(bt->lchild);//建左子树 		pre_crt(bt->rchild);//建右子树 	} 	else  		bt = NULL; }

3.删除二叉树

void dis(tree &bt)//删除二叉树 { 	if(bt) 	{ 		dis(bt->lchild);//删左子树 		dis(bt->rchild);//删右子树 		delete bt;//释放父结点 	} }

4.插入一个结点到排序二叉树中

void insert(tree &bt, int n)//插入一个结点到排序二叉树中 { 	if(bt) 	{ 		if(n < bt->data)              insert(bt->lchild, n); 		else if(n > bt->data)              insert(bt->rchild, n); 	} 	else 	{         bt = new node;//新开一个空间 		bt->data = n; 		bt->lchild = bt->rchild = NULL; 	} }	


5.在排序二叉树中查找一个数,找到返回该结点,否则返回NULL

tree findn(tree bt, int n)  //在二叉树中查找一个数,找到返回该结点,否则返回NULL。 { 	if(bt) 	{         if(n < bt->data)              findn(bt->lchild, n); 		else if(n > bt->data)              findn(bt->rchild, n); 		else              return bt; 	}	     else          return NULL; }


6.用嵌套括号表示法输出二叉树

void print(tree bt)//用嵌套括号表示法输出二叉树 {	     if(bt) 	{ 		cout << bt->data;         if(bt->lchild || bt->rchild) 		{ 			cout << '(';             print(bt->lchild); 			if(bt->rchild)                  cout << ',';             print(bt->rchild); 			cout << ')'; 		} 	} }

【树的计数问题】

相似二叉树:两者都为空树或者两者均不为空树,且它们的左右子树分别相似。

等价二叉树:两者不仅相似,而且所有对应结点上的数据元素均相同。

二叉树的计数问题就是讨论具有 n 个结点、互不相似的二叉树的数目 Bn 。

一般情况,一棵具有 n(n>1) 个结点的二叉树可以看成是由一个根结点、一棵具有 i 个结点的左子树和一棵具有 n-i-1 个结点的右子树组成,其中0<=i<=n-1,当n很小时,易得:B0=1,B1=1,B2=2,B3=5


化为函数,即得:


【例题】

  1. 二叉树的存储结构:点击这里
  2. 二叉树的基本操作:点击这里

文章来源: 二叉树
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!