文章目录

    • 一、基本概念
      • 1.树的定义
      • 2.树的节点
      • 3.树的性质
      • 4.基本操作
    • 二、二叉树
      • 1.二叉树的特点
      • 2.特殊二叉树
      • 3.性质
      • 4.存储结构
        • (1)二叉链表
        • (2)三叉链表
      • 5.线索化
    • 三、树和森林
      • 1.树
      • 2.森林
    • 四、Huffman树及编码
      • 1.基本概念
      • 2.哈夫曼树
      • 3.编码
    • 文章索引

一、基本概念

1.树的定义

树:n(n≥0)个结点的有限集。在任何一棵非空树中:
1.有且仅有一个特定称为根的结点
2.n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中Ti称为树的子树。

  • 树的度

    树中各结点的度的最大值

  • 树的深度

    (高度):树中叶子结点所在的最大层次

2.树的节点

数据元素及若干指向其子树的分支

  • 节点的度

    节点拥有子树的个数

  • 节点的层次

    设根结点的层次为1,第l层结点的层次为L,则第l层结点的子树根结点的层次为L+1

  • 节点的关系

    • 孩子(结点)

      结点子树的根称为该结点的孩子

    • 双亲(结点)

      结点是其孩子的双亲

    • 祖先(结点)

      从根到该结点所经分支上的所有结点

    • 子孙(结点)

      以该结点为根的子树中的任一结点

    • 兄弟(结点)

      同一双亲的孩子互称兄弟

    • 堂兄弟(结点)

      其双亲在同一层的结点互称堂兄弟

  • 节点的分类

    • 叶子

      (终端结点):度为零的结点

    • 非终端结点

      (分支结点):度不为零的结点

3.树的性质

层次性
递归性

4.基本操作

InitTree(&T); CreateTree(&T,definition);
ClearTree(&T); TreeEmpty(T);
TreeDepth(T); Root(T);
Value(T,cur_e); Assign(T, &cur_e, value);
Parent(T, cur_e);
LeftChild(T,cur_e);
RightSibling(T,cur_e);
InsertChild(&T,&p,i,c); DeleteChild(&T,&p,i);
TraverseTree(T,visit());
DestroyTree(&T);

二、二叉树

1.二叉树的特点

每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点)
二叉树的子树有左右之分,其次序不能任意颠倒,分别称为左子树和右子树,左子树和右子树的根称为其双亲的左、右孩子

2.特殊二叉树

  • 满二叉树

    一棵深度为k且正好有2k-1个结点的二叉树称为满二叉树

  • 完全二叉树

    深度为k、有n个结点的二叉树中的各结点与深度为k的满二叉树编号从1到n的结点一一对应 约定编号从根结点开始,自上而下,从左到右
    所有的叶子结点都出现在最大的2层上 任一结点,若其右子树最大高度为L,则其左子树最大高度为L或L+1

3.性质

  • 性质1:

    在二叉树的第i层上至多有2i-1个结点(i≥1)。

    采用归纳法证明此性质。
    当i=1时,只有一个根结点,2i-1=20 =1,命题成立。
    假设第i-1层上至多有2i-2个结点。
    由于二叉树每个结点的度最大为2,故在第i层上最大结点数为第i-1层上最大结点数的二倍,即2×2i-2=2i-1。
    命题得证。

  • 性质2:

    深度为k的二叉树至多有2k-1个结点(k≥1).

  • 性质3:

    对任何一棵二叉树,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。

    证明:
    设二叉树中度为i的结点数为ni,二叉树中总结点数为n,则有:
    n=n0+n1+n2 (1)
    从二叉树中的分支数B看,除根结点外,其余结点都有一个进入分支,则有:n=B+1。
    由于这些分支都是由度为1和2的结点射出的,所以有:
    B=n1+2n2
    n=B+1=n1+2n2+1 (2)
    综合式(1)和(2)得到: n0+n1+n2=n1+2n2+1
    n0=n2+1

  • 性质4:

    具有n个结点的完全二叉树的深度为log2n(下取整) +1

    证明:
    假设此二叉树的深度为k,则根据性质2及完全二叉树的定义可得: 2k-1-1< n ≤ 2k-1
    即: 2k-1 ≤ n < 2k
    取对数得: k-1≤log2n<k, 即:log2n<k≤log2n+1
    ∵ k是整数 ∴ k= log2n(下取整) +1

  • 性质5:

    若对一棵有n个结点的完全二叉树结点进行顺序编号,对任一结点i(1≤i≤n),有:

    (1)若i=1,则i是二叉树的根,无双亲;若i>1,则其双亲编号是i/2(下取整)
    (2)若2i>n,则i为叶子结点,无左孩子;否则,其左孩子编号是2i。
    (3)若2i+1>n,则i无右孩子;否则,其右孩子编号是2i+1。

4.存储结构

  • 顺序存储结构:适用于完全二叉树

    • 特点

      特点:用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树的结点。此时可利用性质5很方便地求出结点之间的关系。

    • 缺点

      对一般二叉树,可将其每个结点与完全二叉树上同一位置上的结点对照,存储在一维数组的相应分量中。可能对存储空间造成极大的浪费。

    • C语言描述

      #define MAX_TREE_SIZE 100 typedef ElemType SqBiTree[MAX_TREE_SIZE+1]; //0号单元空闲,1号单元存储根结点

(1)二叉链表

  • 二叉树的二叉链表C语言描述

      typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;
    
  • 基于二叉链表的基本操作

    • 遍历二叉树

      按某条搜索路径巡访二叉树中的每一个结点,使每一个结点均被访问一次且仅被访问一次。

      • 基本遍历操作

        • 先序遍历

          访问根结点;
          先序遍历左子树;
          先序遍历右子树;

          • 递归

            • 算法分析

              若二叉树为空,则空操作,否则:
              1访问根节点
              2先序遍历左子树
              3先序遍历右子树

            • 代码实现

                Status PreorderTraverse(BiTree T, Status(*visit)(ElemType)){if (T != NULL)//二叉树非空{if (visit(T->data))//访问节点,且访问成功{if (PreorderTraverse(T->lchild, visit))//先序遍历左子树{if (PreorderTraverse(T->rchild, visit))//先序遍历右子树{return OK;}}}           return ERROR;}else return OK;}//二叉树先序遍历算法
              
          • 非递归

            • 算法分析

              1将根节点入栈并访问,
              2依次将左孩子入栈,直到没有左孩子,将栈顶的空指针弹出,
              3将栈顶节点出栈并将其右孩子入栈访问,重复2

            • 代码实现

                void PreorderTraverse1(BiTree T, Status(*visit)(ElemType)){SqStack S;//建立栈BiTree p;InitSqStack(S); SqPush(S, T);//根节点入栈while (SqStackEmpty(S) == FALSE)//栈不空时{while (GetTopSq(S, p) && p)//当栈顶指针不为空{visit(p->data);//访问栈顶指针的数据SqPush(S, p->lchild);//将左孩子入栈}SqPop(S, p);//弹出栈顶的空指针if (SqStackEmpty(S) == FALSE){SqPop(S, p);SqPush(S, p->rchild);}}}//先序遍历的非递归算法
              
        • 中序遍历

          中序遍历左子树;
          访问根结点;
          中序遍历右子树;

          • 递归

            • 算法分析

              若二叉树为空,则空操作,否则:
              1先序遍历左子树
              2访问根节点
              3先序遍历右子树

            • 代码实现

                Status InorderTraverse(BiTree T, Status(*visit)(ElemType)){if (T != NULL){if (InorderTraverse(T->lchild, visit)){if (visit(T->data)){if (InorderTraverse(T->rchild, visit)){return OK;}}}return ERROR;}else return OK;}//二叉树中序遍历算法
          • 非递归

            • 算法分析

              1将根节点入栈并访问,
              2依次将左孩子入栈,直到没有左孩子,将栈顶的空指针弹出,
              3将栈顶节点出栈访问并将其右孩子入栈,重复2

            • 代码实现

                void InorderTraverse1(BiTree T, Status(*visit)(ElemType)){SqStack S;InitSqStack(S); SqPush(S, T);BiTree p;while (SqStackEmpty(S) == FALSE){while (GetTopSq(S, p) && p)   SqPush(S, p->lchild);SqPop(S, p);if (!SqStackEmpty(S)){SqPop(S, p);visit(p->data);SqPush(S, p->rchild);}}} //中序遍历非递归算法
              
        • 后序遍历

          后序遍历左子树;
          后序遍历右子树;
          访问根节点

          • 递归

            • 算法分析

              若二叉树为空,则空操作,否则
              1先序遍历左子树
              2先序遍历右子树
              3访问根节点

            • 代码实现

                Status PostorderTraverse(BiTree T, Status(*visit)(ElemType)){if (T != NULL){if (PostorderTraverse(T->lchild, visit)){if (PostorderTraverse(T->rchild, visit)){if (visit(T->data)){return OK;}}}return ERROR;}else return OK;}//二叉树后序遍历算法
          • 非递归

            • 算法分析

              1构造空栈.定义两个指针r和p,r记录栈顶节点,p记录已经访问过的节点.
              2依次将左孩子入栈,弹出空指针,如果访问过的节点是栈顶节点的右孩子,就访问栈顶节点更新p并出栈。更新栈顶r。
              3将r的右孩子入栈,重复2

            • 代码实现

                void PostorderTraverse1(BiTree T, Status(*visit)(ElemType)){SqStack S;BiTree p;BiTree r;int i;InitSqStack(S); SqPush(S, T);while (!SqStackEmpty(S)){while (GetTopSq(S, p) && p)   SqPush(S, p->lchild);//依次将左孩子入栈SqPop(S, p);//将栈顶的空指针出栈while ((i = GetTopSq(S, r)) && r->rchild == p)//如果从右孩子返回,访问节点{visit(r->data);SqPop(S, p);}if (i) SqPush(S, r->rchild);//右孩子入栈}} //后序遍历的非递归算法
              
        • 层序遍历

          • 算法分析

            1构造队列,队头指针p
            2根节点非空则入队
            3队列不空则出队访问,并将非空的左右孩子入队

          • 代码实现

              void LevelorderTraverse(BiTree T, Status(*visit)(ElemType)){BiTree p;p = T;SqQueue Q;InitSqQueue(Q);if (p) EnSqQueue(Q, p);while (!SqQueueEmpty(Q)) // 队列不空{DeQueue(Q, p);  visit(p->data);if (p->lchild)  EnSqQueue(Q, p->lchild);if (p->rchild)  EnSqQueue(Q, p->rchild);}} //层序遍历二叉树
            
      • 复杂度分析

        • 递归

          • 算法复杂度分析

            • 时间复杂度

            根据公式T(n)=2T(n/2)+1=2(2T(n/4)+1)+1=2logn+2(logn-1)+…+2+1 ~=
            n,所以时间复杂度为O(n)。

            • 空间复杂度

              空间复杂度与系统堆栈有关,系统栈需要记住每个节点的值,所以空间复杂度为O(n)。

          • 优缺点

            • 优点

              算法描述简单,系统维护栈,自己不用考虑空间的管理。遍历方式单一,不利于后续的扩展操作。

            • 缺点

              遍历方式单一,不利于后续的扩展操作。便于在遍历时进行其他操作,遍历操作灵活。

        • 非递归

          • 算法复杂度分析

            • 时间复杂度

              每个节点遍历一次,所以时间复杂度为O(n),n为结点数。

            • 空间复杂度

              由于不管是先序遍历还是中序遍历以及后序遍历,我们都需要利用一个辅助栈来进行每个节点的存储打印,所以每个节点都要进栈和出栈,不过是根据那种遍历方式改变的是每个节点的进栈顺序,空间复杂度为O(n),n为结点数。

          • 优缺点

            • 优点

              便于在遍历时进行其他操作,遍历操作灵活。

            • 缺点

              算法较复杂,自己维护栈易出错。

      • 遍历操作的应用

        • 先序创建二叉树

          • 算法分析

            首先读入数据,如果数据不是终止符则申请空间创建根节点,如果是终止符则创建空树,接着先序创建左子树,然后先序创建右子树。

          • 代码实现

              Status CreateBiTree(BiTree& T){ ElemType ch;scanf("%c", &ch);if (ch == '#') T = NULL;//空指针标志else{if ((T = (BiTree)malloc(sizeof(BiTNode))) == NULL)//创建失败,返回错误值{exit(OVERFLOW);}else{T->data = ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}}return OK;}//先序创建一棵二叉树,由指针T指向其根结点的指针
            
        • 求二叉树中叶子结点数目

          • 算法分析

            通过可变参数i传出叶子节点的数量,i初始化为0。如果树不为空,判断是否时叶子节点,如果是叶子,计数加一。然后对左子树计数,对右子树计数。

          • 代码实现

              Status POLeafNodeNum(int& i, BiTree& T)//通过可变参数i传出叶子节点的数量,i初始化为0{if (T != NULL)//T为空时结束{if (T->lchild == NULL && T->rchild == NULL)//递归的出口、叶子节点的判断依据:无左右孩子i++;POLeafNodeNum(i, T->lchild);//对左子树计数POLeafNodeNum(i, T->rchild);//对右子树计数}return OK;}// 求二叉树中叶子结点的数目
            
        • 求二叉树深度

          • 算法分析

            空树的深度为0,书的深度为左右子树深度的最大值加一。

          • 代码实现

              int depth(BiTree T){if (T == NULL) return 0;//空树的深度为零int depthl, depthr;depthl = depth(T->lchild);depthr = depth(T->rchild);return (depthl > depthr ? depthl : depthr) + 1;//树的深度为左右子树的深度最大值加1}//利用遍历求二叉树的深度
            
        • 判断二叉树是否相似

          • 算法分析

            T1 是空树,T2是空树,则相似
            T1 是空树,T2不是空树则不相似
            T1 是非空树,T2是空树,则不相似
            T1、T2 是非空树,左右子树相似则相似,否则不相似

          • 代码实现

              Status SimilarTree(BiTree& T1, BiTree& T2) {if (T1 == NULL){if (T2 == NULL) return TRUE;// T1 是空树,T2是空树,则相似else return FALSE;// T1 是空树,T2不是空树则不相似}else {if (T2 == NULL) return FALSE;// T1 是非空树,T2是空树,则不相似else // T1、T2 是非空树{ if (SimilarTree(T1->lchild, T2->lchild) && SimilarTree(T1->rchild, T2->rchild))return TRUE;//左右子树相似则相似else return FALSE;}}}//判断两棵二叉树是否相似
            

(2)三叉链表

  • 二叉树的三叉链表C语言描述

      typedef struct TriTNode{ElemType data;struct TriTNode *lchild,*rchild,*parent;}TriTNode,*TriTree;//增加了指向双亲节点的指针
    

5.线索化

  • 目的
    无法直接得到结点在任意序列中的前驱和后继信息,这种信息只能在遍历的动态过程中才能得到
    保存这种在遍历过程中得到的信息:

    (1)在每个结点上增加两个指针域fwd和bkwd,分别指向结点在按照某种顺序遍历时得到的前驱和后继。
    缺点:存储密度低
    (2)在有n个结点的二叉链表中必定存在n+1个空链域,可用它们存放结点的前驱和后继。 若结点有左子树,lchild指向左孩子,否则指向其前驱 若结点有右子树,rchild指向右孩子,否则指向其后继

    充分利用二叉链表的空指针域,保存动态遍历过程中得到的结点前驱和后继的信息

  • 术语

    • 线索

      指向结点前驱或后继的指针

    • 线索二叉树

      加上线索的二叉树

    • 线索化

      对二叉树以某种次序遍历使其变为线索二叉树的过程

三、树和森林

1.树

  • 树的双亲表示法

    • 实现

      用结构数组存放树的结点,每个分量含两个域: 数据域:存放结点本身信息 双亲域:指示本结点的双亲结点在数组中位置,根节点为-1

    • 特点

      找孩子节点需要遍历整个数组。 找双亲容易,找孩子困难

  • 树的多重链表表示

    • 实现

      多重链表:每个结点有多个指针域,分别指向其孩子结点。

    • 特点

      1.结点同构:结点的指针个数相等,为树的度D.操作简便,浪费空间
      2结点不同构:结点指针个数不等,为该结点的度d.链表中无空指针,无空间浪费,但操作不便

  • 树的孩子链表表示

    • 实现

      每个结点的孩子组织成一个单链表,用结构数组存放树的结点,每个分量含两个域:
      数据域:存放结点本身信息
      指针域:指向每个孩子链表的首元结点 (类似有向图的邻接表存储)

    • 特点

      便于涉及孩子结点操作的实现
      不适用于求结点的双亲

  • 树的孩子兄弟表示法

    • 实现

      树的孩子兄弟表示法: 链表中结点的两个指针域分别指向该结点的第一个孩子和下一个兄弟。

    • 二叉链表存储

      typedef struct CSNode
      {ElemType data;struct CSNode *firstchild, *nextsibling;
      }CSNode,*CSTree;
      
    • 特点

      优点:

      易于找结点孩子 便于导出树与二叉树的转换关系

      缺点:

      不易查找结点的双亲
      破坏了树的层次

    • 转化方法

      • 树->二叉树

        步骤1:加线-在兄弟之间加一连线
        步骤2:抹线-对每个结点,除了其第1个孩子外,去除其与其余孩子之间的关系
        步骤3:旋转-以树的根结点为轴心,将整树顺时针转45°

      • 二叉树->树

        步骤1:加线-若p结点是双亲结点的左孩子,将p的右孩子以及沿右分支找到的所有右孩子与p的双亲连线。
        步骤2:抹线-抹掉原二叉树中双亲与右孩子之间的连线
        步骤3:将结点按层次排列,形成树结构

    • 遍历

      • 先根遍历

        若树不空,先访问根结点,再依次先根遍历各棵子树。
        对应二叉链表的先序遍历。

      • 后根遍历

        若树不空,先依次后根遍历各棵子树,再访问根结点
        对应二叉链表的中序遍历

      • 层次遍历

        若树不空,自上而下自左至右访问树中每个结点

2.森林

  • 森林&二叉树

    • 森林和二叉树的转换规则

      • 森林->二叉树

        设森林F={T1,T2,……Tm},二叉树B=(root,LBT,RBT)
        森林转化成二叉树的规则
        若F为空(m = 0),B为空;
        若F不空(m ≠0),
        B的根root(B)是F中第一棵树T1的根root(T1);
        左子树LBT从T1根结点的子树森林 {T11, T12, …, T1m }转换而来;
        右子树RBT是从森林F’={T2, T3, …, Tn} 转换而来。

      • 二叉树->森林

        二叉树转换为森林的规则
         若B为空, F为空;
         若B非空,
        则F中第一棵树T1的根为二叉树的根root(B);
        T1根的子树森林F1= (T11, T12, …, T1m)由B的左子树LBT转换而来;
        F 中除 T1 外其余树组成的森林F’={ T2, T3, …, Tn } 由B的右子树 RBT 转换而来。

    • 遍历

      • 先序遍历(对应二叉树的先序遍历)

        先根遍历森林中的每一棵树:
        访问第一棵树的根。
        先根遍历第一棵树中根结点的子树森林。
        先根遍历除去第一棵树之后剩余的树构成的森林。

      • 中序遍历(对应二叉树的中序遍历)

        后根遍历森林中的每一棵树:
        中序遍历第一棵树中根结点的子树森林。
        访问第一棵树的根。
        中序遍历除去第一棵树之后剩余的树构成的森林。

四、Huffman树及编码

1.基本概念

  • 路径

    从树中一个结点到另一个结点之间的分支。

  • 路径长度

    路径上的分支数目。

  • 树的路径长度

    从树根到每个结点的路径长度之和。

  • 结点的带权路径长度

    从该结点到树根的路径长度与结点上的权值的乘积。

  • 树的带权路径长度WPL(叶子)

    树中所有叶子结点的带权路径长度之和。

2.哈夫曼树

已知n个权值{w1,w2,…wn},构造一棵有n个叶子结点的二叉树,第i个叶子结点的权值是wi,则其中带权路径长度最小的二叉树称为赫夫曼树(Huffman
tree)或最优二叉树。

  • Huffman树的构造

    • 步骤1:
      根据给定的n个权值{w1, w2, …, wn},构造n棵二叉树的集合F = {T1, T2, …, Tn},Ti(1≤i≤n)只有一个带权值wi的根结点,其左、右子树均为空。
    • 步骤2:
      在F中选取两棵根结点权值最小的二叉树,分别作为左、右子树构造一棵新二叉树。置新二叉树的根结点的权值为其左、右子树上根结点的权值之和。
    • 步骤3:
      在F中删去这两棵二叉树,把新的二叉树加入F 。
    • 步骤4:
      重复步骤2和步骤3 直到F中仅剩下一棵树为止。这棵树就是Huffman树。
  • 赫夫曼树的存储结构

    一棵有n个叶子结点的Huffman树共有2n-1个结点,可存储在长度为2n-1的一维数组中。

    typedef struct
    {unsigned int weight;
    unsigned int parent, lchild, rchild;
    }HTNode,*HuffmanTree;
    
  • 构造Huffman树的算法

    Status CreateHuffmanTree(HuffmanTree& HT, int* x, int n)
    {int *w=x;
    int m, i;
    HuffmanTree p;
    if (n <= 1) return ERROR;
    m = 2 * n - 1;
    HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));//0号单元未用
    for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
    {p->weight = *w;p->lchild = 0;p->rchild = 0;p->parent = 0;
    }
    for (; i <= m; ++i, ++p)
    {p->weight = 0;p->lchild = 0;p->rchild = 0;p->parent = 0;
    }
    int s1, s2;
    //s1是最小的,s2是次小的
    for (i = n + 1; i <= m; ++i)
    {Select(HT, i - 1, s1, s2);HT[s1].parent = i; HT[s2].parent = i;HT[i].lchild = s1; HT[i].rchild = s2;HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
    return OK;
    }void Select(HuffmanTree HT, int n, int& s1, int& s2)
    {int min1 = 1000, min2 = 1000;
    for (int i = 1; i <= n; i++)
    {if (HT[i].parent == 0){if (HT[i].weight <= min1){min2 = min1;min1 = HT[i].weight;s2 = s1;s1 = i;}else if (HT[i].weight > min1 && HT[i].weight <= min2){min2 = HT[i].weight;s2 = i;}else{continue;}}else{continue;}
    }
    }
    

3.编码

  • 类型

    • 固定长度编码

      每个被编码对象的码长相等。
      优点:码长等长,易于解码;
      缺点:被编码信息总码长较长;

    • 不等长编码

      每个被编码对象的码长不等。
      优点:总码长较短;
      缺点:不易解码,解码容易产生二义性

  • 前缀编码

    任一字符的编码不是其它字符编码的前缀

  • Huffman编码

    码长最短的二进制前缀编码:以n种字符出现频率为权,设计一棵Huffman树,由此得到的编码称为Huffman编码

  • Huffman编码算法

    Status HuffmanCoding(HuffmanCode& HC, HuffmanTree HT, int n){HC = (HuffmanCode)malloc((n + 1) * sizeof(char*));//和Huffman树的叶子节点对应,0号下标不存储编码char* cd;//临时存放编码cd = (char*)malloc(n * sizeof(char));//有n个叶子节点的树的深度不超过n-1cd[n - 1] = '\0';//最后一个字符存放字符串结尾标志int start;//标记编码的起始下标for (int i = 1; i <= n; ++i)//循环为每一个叶子编码{int f;//存放双亲下标int c;//存放孩子下标start = n - 1; //起始下标初始化为n-1                     for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)//从叶子节点向根节点if (HT[f].lchild == c)   cd[--start] = '0';//左孩子为0,更新起始下标else  cd[--start] = '1';//右孩子为1,更新起始下标HC[i] = (char*)malloc((n - start) * sizeof(char)); //为编码分配空间        strcpy(HC[i], &cd[start]);//复制到已分配的空间}//forfree(cd);return OK;} //HuffmanCoding
    
  • Huffman解码算法

   Status HuffmanDeCoding(HuffmanTree HT, char* decode, int n, char* key,char* ch)//decode是待解码字符串,n是字符个数,key是解码结果,ch是字符集合{int j = 0;int k = 2 * n - 1;for (int i = 0; i < strlen(key); i++){if (key[i] == '0'){k = HT[k].lchild;}else{k = HT[k].rchild;}if (HT[k].lchild == 0 || HT[k].rchild == 0){decode[j] = ch[k - 1];j++;k = 2 * n - 1;}}decode[j] = '\0';return OK;}

文章索引

  • 【知识索引】【数据结构(C语言)】
  • 【数据结构(C语言)】数据结构-表
  • 【数据结构(C语言)】数据结构-树
  • 【数据结构(C语言)】数据结构-图
  • 【数据结构(C语言)】数据结构-查找
  • 【数据结构(C语言)】数据结构-内部排序

【数据结构(C语言)】数据结构-树相关推荐

  1. c语言编程文件中删除数据结构,C语言数据结构实战(一)顺序表的插入与删除

    今天学习了思成老师的数据结构实战教程 写了一个顺序表 插入和删除的操作 把源码共享给大家 一共包括list.c stu.h main.c list.h   .h文件是头文件 需要引入 具体的功能我都已 ...

  2. 栈的应用行编辑数据结构c语言,数据结构题典022:栈的应用——行编辑程序(C语言版)...

    编写程序实现从终端接收用户输入的数据,并存入用户数据区.输入#表示上一字符无效,输入@表示当前输入行整行无效. /* * line editor by using stack. * * fduan, ...

  3. 平衡查找树C语言程序,C语言数据结构之平衡二叉树(AVL树)实现方法示例

    本文实例讲述了C语言数据结构之平衡二叉树(AVL树)实现方法.分享给大家供大家参考,具体如下: AVL树是每个结点的左子树和右子树的高度最多差1的二叉查找树. 要维持这个树,必须在插入和删除的时候都检 ...

  4. 数据结构c语言版胡学刚答案,哈夫曼树的建立与实现(最终版)最新版

    <哈夫曼树的建立与实现.doc>由会员分享,可免费在线阅读全文,更多与<哈夫曼树的建立与实现(最终版)>相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索 ...

  5. C语言数据结构【手抄版】第五章 树和二叉树【上篇】

    注意:文中彩色代码均在Visual Studio 2022编译器中编写,本文为C语言数据结构手抄版,文中有部分改动,非原创. 目录 5.1.树的基本概念和术语 1.树的定义 2.树的表示法 3.基本术 ...

  6. 数据结构c语言版二叉树的顺序存储表示,数据结构(十一) -- C语言版 -- 树 - 二叉树基本概念...

    内容预览 零.读前说明一.二叉树相关概念1.1.定义1.2.性质1.3.满二叉树与完全二叉树1.3.1.满二叉树1.3.2.完全二叉树1.3.3.特点延伸 二.二叉树储存结构2.1.顺序结构存储2.2 ...

  7. 数据结构(十九) -- C语言版 -- 树 - 树、森林、二叉树的江湖爱恨情仇、相互转换

    内容预览 零.读前说明 一.树转换为二叉树 二.二叉树转换为树 三.二叉树转换为森林 四.森林转换为二叉树 五.树与森林的遍历 5.1.树的遍历 5.2.森林的遍历 零.读前说明 本文中所有设计的代码 ...

  8. 数据结构(C语言版)严蔚敏(树、二叉树的相关概念笔记)

    数据结构(C语言版)严蔚敏(树的相关概念笔记) 1. 树中一个节点的孩子个数称为该节点的度,树中节点的最大度数称为树的度: 2. 度大于0的节点称为[分支节点](非终端节点),度为0的节点称为[叶子节 ...

  9. 数据结构(十一) -- C语言版 -- 树 - 二叉树基本概念

    内容预览 零.读前说明 一.二叉树相关概念 1.1.定义 1.2.性质 1.3.满二叉树与完全二叉树 1.3.1.满二叉树 1.3.2.完全二叉树 1.3.3.特点延伸 二.二叉树储存结构 2.1.顺 ...

最新文章

  1. 微型计算机中 存储器的主要功能是,在计算机中存储器的主要作用是什么?
  2. 泛函编程—模板函数_类模板
  3. 隐马尔科夫模型HMM自学 (2)
  4. OpenGL Gouraud着色法的实例
  5. 实体类为什么要用包装类而不用基本类型
  6. 实训09.08:简单的算法练习
  7. Cortex-M3异常
  8. 4广联达4代锁安装6.0_Aspen Plus 8.4 软件安装教程
  9. 免费rar密码破解工具排行榜
  10. 关于sd卡的读取权限
  11. 如何查找某一个数据?
  12. SAP 预收款和收款清账
  13. 计算机科学导论-绪论
  14. 找工作千万不要找外包?BAT互联网大厂外包亲身经历
  15. 扎根基层一线 助力社区(村)发展
  16. 可穿戴设备数据安全及隐私保护概论
  17. 代码随想录Day01 | LeetCode704.二分查找、LeetCode27.移除元素
  18. 大学综评自招面试 计算机专业,沪9高校举行自招面试 高中学生综合素质纪实报告成重要参考...
  19. 高一计算机专业班主任工作总结,高中计算机专业班主任工作总结.doc
  20. 解惑:不要在多门语言间徘徊,把一门语言玩熟了,其他语言都是纸老虎...

热门文章

  1. linux学习笔记:更换国内网易163 yum 源
  2. windows_server2012搭建iis并配置http重定向 iis转发
  3. pb数据窗口怎么调用视图_大数据架构如何做到流批一体?
  4. android只有域名打包封装成apk,一个Android Studio工程根据网址打包出不同的apk
  5. java书籍_腾讯大牛每天都要花一小时读的这11本java电子书籍,你还不看?
  6. frpc客户端 linux安装,centos配置frp服务端,与客户端
  7. mat分析dump分析_使用Eclipse Memory Analyzer Tool(MAT)分析线上故障(一)
  8. php 字符串进行计算_PHP eval() 函数把字符串按照 PHP 代码来计算
  9. 有计算机考试励志的文案,关于考试的句子励志
  10. java 文件大小,如何在Java中获取文件大小