<<大话数据结构>>之浅谈二叉树

编程中我们会遇到多少挫折?表放弃,沙漠尽头必是绿洲。
大话数据结构修改版


学习二叉树的意义


由于二叉树的知识更倾向于理论,所以我们在实际应用开发过程中使用的并不多,但是二叉树作为数据结构的一个重要的组成部分,所以,在程序猿的面试过程中,会经常遇到二叉树知识相关问题.所以学习二叉树是相当有必要的.


二叉树的结构和特点


想要了解二叉树的相关知识,就要先要了解二叉树的结构和特点.只有了解二叉树的结构和它的特点,才能更好的学习二叉树.

我们先看一下二叉树的定义是如何的.

二叉树的结构
二叉树是 n (n >= 0)个结构的有限集合,改集合或者为空集(称为空二叉树),或者有一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的二叉树组成.
二叉树的特点:
  • 1.每个节点嘴都有两棵子树,所以二叉树中不存在度大于2的结点.注意不是只有两棵子树,而是最多有两棵子树,所以说没有子树或者有一颗子树也是可以的.
  • 2.左子树和右子树是有顺序的,次序不能任意点到.就像人是双手、双脚,但显然左手、左脚和右手、右脚是不一样的,右手戴左手套、右脚穿左鞋都会及其别扭和难受.
  • 3.即时树种的某一个节点只有一棵子树,也要区分他是左子树还是右子树.


二叉树的五种基本形态:

二叉树的五种基本形态


特殊二叉树


对于特殊二叉树,我只想谈一下满二叉树和完全二叉树,因为这两种二叉树容易发生混乱.

满二叉树:

定义: 在一棵二叉树中,如果所有的分支节点都存在左子树和右子树,并且所有叶子都在同一层面上,这样的二叉树成为满二叉树.

下面我们看一下满二叉树和普通的二叉树的区别以及构成


满二叉树与普通二叉树.jpg
满二叉树的特点:
  • (1) 满二叉树的叶子只能出现在最下一层,出现在其它层就不可能达成平衡.
  • (2) 非叶子节点的度一定是2.
  • (3) 在同样深度的热茶树中,满二叉树的节点个数最多,叶子数最多.


完全二叉树:

其实学习完全二叉树要与满二叉树对比着看,首先我们先看一下完全二叉树的定义

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

满二叉树与完全二叉树
完全二叉树的特点:
  • (1) 完全二叉树的叶子节点只能出现在最下面的两层.
  • (2) 最下层的叶子一定集中在左部的连续位置.
  • (3) 倒数二层,若有叶子节点,则一定在右部的连续位置/
  • (4) 如果结点度为1,则该结点只有有孩子,即不存在只有右子树的情况.
  • (5) 同样结点书的二叉树,完全二叉树的深度最小.


完全二叉树与满二叉树的区别:

看完上面的完全二叉树和满二叉树的定义和特点,可能对两种特殊的二叉树有所混淆,所以我们来区分一下两种二叉树,首先从字面上区分,"完全"和"满"的差异,满二叉树一定是一棵完全二叉树,但完全二叉树不一定是满的.其实,完全二叉树的所有节点与同样深度的满二叉树,他们按层序编号相同的结点,是一一对应的,这里有个关键词是按层序编号.


二叉树的性质


二叉树的性质在面试题中会经常提到并且使用它进行计算面试题中的题目.那么接下来,看一下二叉树都有一些什么的性质吧.

二叉树性质1
内容:在二叉树的第 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) 个结点的结论.

二叉树基本图.jpg
二叉树性质2
内容: 深度为 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)的结论.

二叉树性质3
内容:对于任意一棵二叉树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;



二叉树性质4
内容:具有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为深度)

二叉树性质5
内容:如果对一棵有 n 个结点的完全二叉树(其深度为[log (2) n] + 1) 的结点按层序编号(从第1层到第[log (2) n] + 1 层,每一层从左到右),对任一结点i (1 <= i <= n) 有:
  • 1.如果 i = 1 ,则结点i是二叉树的根,无双亲;如果i > 1,则其双亲是结点 [ i /2 ];
  • 2.如果2i > n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点2i;
  • 3.如果2i +1 > n,则结点i无右孩子;否则其右孩子是结点2i +1;

我们还是以下面这一棵二叉树进行验证,通过对性质5的一一比对,发现性质5是正确的,这里我就不一一比对了.



二叉树的遍历


二叉树的遍历多种多样,这里我只说,三种常用的遍历,前序遍历,中序遍历,后续遍历.我们在面试当中会遇到当量的二叉树遍历的问题.

前序遍历

####### 内容: 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
#######若二叉树为空则结束返回,否则:

  • #######(1)访问根结点。
  • #######(2)前序遍历左子树。
  • #######(3)前序遍历右子树 。
前序遍历

那么接下来,我们看一下用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;
}

中序遍历
内容:中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。即:
若二叉树为空则结束返回,否则:
  • (1)中序遍历左子树。
  • (2)访问根结点。
  • (3)中序遍历右子树。
中序遍历

我们还是使用递归的思想来进行遍历,不解释,直接上代码

void inOrder(struct BTreeNode *bt){
   if(bt != NULL){
       inOrder(bt->left); /* 中序遍历左子树 */
        printf("%c ", bt->data); /* 访问根结点 */
       inOrder(bt->right); /* 中序遍历右子树 */
      }
       return;
   } 
后序遍历
内容:后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:

若二叉树为空则结束返回,否则:

  • (1)后序遍历左子树
  • (2)后序遍历右子树
  • (3)访问根结点
后序遍历

直接上代码..

void inOrder(struct BTreeNode *bt){
   if(bt != NULL){
       inOrder(bt->left); /* 后序遍历左子树 */
       inOrder(bt->right); /* 后序遍历右子树 */
        printf("%c ", bt->data); /* 访问根结点 */
      }
       return;
  } 

关于数据结构中的二叉树相关知识 就给大家说到这,谢谢大家,希望您能喜欢.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 6,426评论 0 14
  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,741评论 0 19
  • 1.树(Tree): 树是 n(n>=0) 个结点的有限集。当 n=0 时称为空树。在任意一颗非空树中:有且仅有一...
    ql2012jz阅读 982评论 0 3
  • 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
    MinoyJet阅读 1,505评论 0 7
  • 1.树的定义 树是n(n>=0)个结点的有限集.n=0时称为空树.在任意一颗非空树种:(1)有且仅有一个特定的称为...
    e40c669177be阅读 2,796评论 1 14