标签:root 注意 顺序 tps get 控制 多少 集中 keyword
编程中我们会遇到多少挫折?表放弃,沙漠尽头必是绿洲。
由于二叉树的知识更倾向于理论,所以我们在实际应用开发过程中使用的并不多,但是二叉树作为数据结构的一个重要的组成部分,所以,在程序猿的面试过程中,会经常遇到二叉树知识相关问题.所以学习二叉树是相当有必要的.
想要了解二叉树的相关知识,就要先要了解二叉树的结构和特点.只有了解二叉树的结构和它的特点,才能更好的学习二叉树.
我们先看一下二叉树的定义是如何的.
二叉树是 n (n >= 0)个结构的有限集合,改集合或者为空集(称为空二叉树),或者有一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的二叉树组成.
对于特殊二叉树,我只想谈一下满二叉树和完全二叉树,因为这两种二叉树容易发生混乱.
定义: 在一棵二叉树中,如果所有的分支节点都存在左子树和右子树,并且所有叶子都在同一层面上,这样的二叉树成为满二叉树.
下面我们看一下满二叉树和普通的二叉树的区别以及构成
其实学习完全二叉树要与满二叉树对比着看,首先我们先看一下完全二叉树的定义
定义: 对于一棵具有 n 个节点的二叉树按层序编号,如果编号为 i ( 1<= i <= n)的节点与同样深度的满二叉树中编号为 i 的节点在二叉树中位置完全相同,则这棵二叉树成为完全二叉树.
看完上面的完全二叉树和满二叉树的定义和特点,可能对两种特殊的二叉树有所混淆,所以我们来区分一下两种二叉树,首先从字面上区分,"完全"和"满"的差异,满二叉树一定是一棵完全二叉树,但完全二叉树不一定是满的.其实,完全二叉树的所有节点与同样深度的满二叉树,他们按层序编号相同的结点,是一一对应的,这里有个关键词是按层序编号.
二叉树的性质在面试题中会经常提到并且使用它进行计算面试题中的题目.那么接下来,看一下二叉树都有一些什么的性质吧.
内容:在二叉树的第 i 层上有至多 2^( i-1) 个结点 (i >= 1).
如下图,
第一层是根节点,只有一个,所以是 2^(1-1) = 2^0 = 0.
第二层有两个,2^(2-1) = 2 ^ 1 = 2.
第三层有四个,2^(3-1) = 2 ^ 2 = 4.
所以通过数据归纳法的论证,很容易得到二叉树的第 i 层上至多有2(i -1) 个结点的结论.
内容: 深度为 k 的二叉树至多有 2^k - 1 个节点(k >= 1).
还是上面的图,深度为k的意思就是有K层的二叉树.
如果有一层,至多有1 = 2 ^ 1 -1 个结点.
如果有两层,至多有1 + 2 = 2^2 -1个结点.
如果有三层,至多有1 + 2 + 4 = 2^3 -1个结点.
所以通过数据归纳法的论证,很容易得到深度为 k 的二叉树至多有 2^k - 1 个节点(k >= 1)的结论.
内容:对于任意一棵二叉树T,如果其终端结点数为n0,度为2的结点书为n2,那么有n0 = n2 + 1;
(注:度的解释,一个结点有n个子结点,那么他就是度为n的结点)
终端结点其实就是叶子结点数,而一棵二叉树,除了叶子结点 外,剩下的就是度为1或2的结点数了.我们设n1为度1的节点数.则数的总结点数为 n = n1 +n2 +n0;
我们来看下图,这个二叉树的总结点数为10,它是由A,B,C,D等度为2的结点,F,G,I,J等度为0的叶子结点和E这个度为1的结点组成.总和为4 + 1 + 5 = 10;
再来看一下,下图的总的连接线数为9,用代数表达式就是分支总数= n -1 = n1 + n2 ,因为我们刚才有等式 n = n0 + n1 + n2 ; 所以可以推导出来 n0 +n1 +n2 -1 = n1 +2 * n2, 结论就是n0 = n2 + 1;
内容:具有n个结点的完全二叉树的深度为 [log (2) n] + 1 ([x] 表示不大于x的最大整数) .
一个完全二叉树的结点数一定少于等于同样读书的满二叉树的结点数2k-1,但一定多于2(k-1) -1;
即为2^(k-1) -1 < n <= 2^k-1;由于结点数为整数,所以我们可以简化不等式,所以 2^(k-1) <= n < 2^k,不等式两边去对数 k-1 <= log2n <k ,因此 k = [log (2) n] + 1.(注:k为深度)
内容:如果对一棵有 n 个结点的完全二叉树(其深度为[log (2) n] + 1) 的结点按层序编号(从第1层到第[log (2) n] + 1 层,每一层从左到右),对任一结点i (1 <= i <= n) 有:
我们还是以下面这一棵二叉树进行验证,通过对性质5的一一比对,发现性质5是正确的,这里我就不一一比对了.
二叉树的遍历多种多样,这里我只说,三种常用的遍历,前序遍历,中序遍历,后续遍历.我们在面试当中会遇到当量的二叉树遍历的问题.
####### 内容: 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
#######若二叉树为空则结束返回,否则:
那么接下来,我们看一下用C语言改如果对一棵二叉树进行前序遍历的.
首先,我们使用链表对结点进行定义,并对二叉树进行创建.
typedef struct _BiTNode
{
int data;
_BiTNode *leftChild;
_BiTNode *rightChild;
}BiTNode, *pBiTree;
//创建二叉树, 先序顺序
int CreateBiTree(pBiTree *root)
{
char ch = 0;
fflush(stdin);
if ((ch = getchar()) == ‘a‘)//控制树的结构
{
*root = NULL;
}
else
{
*root = (BiTNode *)malloc(sizeof(BiTNode));
if (!(*root))
{
return RET_ERROR;
}
(*root)->data = GetRandom();
CreateBiTree(&(*root)->leftChild);
CreateBiTree(&(*root)->rightChild);
}
return RET_OK;
}
创建完成二叉树之后,我们使用递归的写一下前序遍历
//前序遍历
void preOrder(struct BiTNode *bt)
{
if(bt != NULL){
printf("%c ", bt->data); /* 访问根结点 */
preOrder(bt->left); /* 前序遍历左子树 */
preOrder(bt->right); /* 前序遍历右子树 */
}
return;
}
内容:中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。即:
我们还是使用递归的思想来进行遍历,不解释,直接上代码
void inOrder(struct BTreeNode *bt){
if(bt != NULL){
inOrder(bt->left); /* 中序遍历左子树 */
printf("%c ", bt->data); /* 访问根结点 */
inOrder(bt->right); /* 中序遍历右子树 */
}
return;
}
内容:后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:
若二叉树为空则结束返回,否则:
直接上代码..
void inOrder(struct BTreeNode *bt){
if(bt != NULL){
inOrder(bt->left); /* 后序遍历左子树 */
inOrder(bt->right); /* 后序遍历右子树 */
printf("%c ", bt->data); /* 访问根结点 */
}
return;
}
关于数据结构中的二叉树相关知识 就给大家说到这,谢谢大家,希望您能喜欢.
标签:root 注意 顺序 tps get 控制 多少 集中 keyword
原文地址:https://www.cnblogs.com/DreamRecorder/p/9243348.html