IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构第五章——树和二叉树 -> 正文阅读

[数据结构与算法]数据结构第五章——树和二叉树

目录

1.树和二叉树的定义

1.1 树的定义

1.2 二叉树的定义

1.3 基本术语

1.4 抽象数据类型定义

2 二叉树

2.1 二叉树的性质

2.2 二叉树的存储结构

1)顺序存储结构

2)链式存储结构(常用)

2.3 遍历二叉树

1)先序遍历

2)中序遍历

3)后序遍历

4)中序遍历非递归算法

5) 层次遍历

2.4 二叉树遍历的应用

1)建立二叉链表

2)复制二叉树

3)计算二叉树深度

4)计算二叉树结点总数

2.5?线索二叉树

3 树和森林

4 哈夫曼树

5 小结



树结构和线性结构的比较
线性结构树结构
第一个数据元素 无前驱根节点 无双亲
最后一个数据元素 无后继叶子结点 无孩子
其他数据元素:一个前驱,一个后继其他结点(中间结点):一个双亲,多个孩子
一对一一对多

2 二叉树

1 满二叉树:深度为k且有 个结点的二叉树。

  1. 每一层上的结点数都是最大结点(每层都满)。
  2. 叶子结点全部都在最底层。

2 完全二叉树:深度为k的,具有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中的结点一一对应

  1. 叶子只可能分布在层次最大的两层上。
  2. 对任一结点,若其右子树的最大层次为i,则其左子树的最大层次必为i或i+1。

【注】在满二叉树中,从最后一个结点开始,连续去掉任意个结点,即是一颗完全二叉树。

2.1 二叉树的性质

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

性质2 深度为k的二叉树至多有2^{k}-1个结点(k≥1)。

性质3 对任何一颗二叉树T,如果其叶子数为,度为2的结点数为,则。

性质4 具有n个结点的完全二叉树的深度为。

(:称作x的底,表示不大于x的最大整数,反之,表示不小于x的最小整数)

(表明完全二叉树结点数n与深度k之间的关系)

性质5 如果有一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1≤≤n):

  1. 双亲(parent)是结点 i/2
  2. 左孩子(lchild)是结点 2i
  3. 右孩子(rchild)是结点 2i+1

(表明完全二叉树双亲结点编号孩子结点编号之间的关系)

2.2 二叉树的存储结构

1)顺序存储结构

按满二叉树的结点层次编号,依次存放二叉树中的数据元素。

 
  • 顺序存储缺点:深度为k的且只有k个结点的单支树需要长度为2^{k}-1的一维数组。 浪费空间,适合存放满二叉树和完全二叉树。?

2)链式存储结构(常用)

? ? ? 2.1 二叉链表

typedef struct BiNode{
   TElemType data;                   //结点数据域
   struct BiNode *lchild,*rchild;    //左右孩子指针
}BiNode,*BiTree;

图?

? ? ? 2.2 三叉链表*?

typedef struct TriNode{
   TElemType data;                   //结点数据域
   struct TriNode *lchild,*parent,*rchild;    //双亲左右孩子指针
}TriNode,*TriTree;

2.3 遍历二叉树

规定先左后右,则有三种情况:

(若二叉树为空,则空操作),否则:

  1. 根左右,DLR——先序遍历(PrdOrderTraverse);
  2. 左根右,LDR——中序遍历(InOrderTraverse);
  3. 左右根,LRD——后序遍历(PostOrderTraverse);
  • ?由二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一一颗二叉树。

?(由先序序列确定根,由中序序列确定左右子树)

【代码部分】

1)先序遍历

Status PrdOrderTraverse (BiTree T){
     if(T==NULL) return OK;             //若二叉树非空
     else
     {
         cout<<T->data;                 //访问根节点
         PrdOrderTraverse(T->lchild);   //先序遍历左子树
         PrdOrderTraverse(T->rchild);   //先序遍历右子树
     }
}

void Pre(BiTree *T){

? ? if(T!=NULL)

? ? {

? ? ?printf ("%d\t",T->data);

? ? ?pre (T->lchild);

? ? ?pre (T->rchild);

? ? }

}

2)中序遍历

Status InOrderTraverse (BiTree T){
     if(T==NULL) return OK;             //若二叉树非空
     else
     {
         InOrderTraverse(T->lchild);   //中序遍历左子树
         cout<<T->data;                 //访问根节点
         InOrderTraverse(T->rchild);   //中序遍历右子树
     }
}

3)后序遍历

Status PostOrderTraverse (BiTree T){
     if(T==NULL) return OK;             //若二叉树非空
     else
     {
         PostOrderTraverse(T->lchild);   //后序遍历左子树
         PostOrderTraverse(T->rchild);   //后序遍历右子树
         cout<<T->data;                 //访问根节点
     }
}

?从递归的角度看,去掉输出语句,三种算法完全相同,访问的路径相同,访问结点的时机和顺序不同。每个结点经过3次。

遍历算法的分析:

  • 时间效率:O_{\left ( n \right )}(每个结点只访问一次)
  • 空间效率:O_{\left ( n \right )}(栈占用的最大辅助空间)

4)中序遍历非递归算法

的思想实现中序遍历。

基本思想:

  1. 建立一个栈;
  2. 根结点进栈,遍历左子树
  3. 根结点出栈,输出根节点,遍历右子树
Status InOrderTraverse (BiTree T){
    BiTree p;
    InitStack (S);
    p=T;                             //初始化一个空栈,指针p指向根节点
    q=new BiTNode;                   //申请结点q,用来存放栈顶出的元素
    while(p||!StackEmpty(S))         //所有元素出栈
    {
       if(p)                         //p非空
        {
          Push(S,p);                 //根指针进栈
          p=p->lchild;               //遍历左子树
        else                         //p非空
        {
          Pop(S,q);
          printf( "%c",q->data);
          cout<<q->data;             //访问根节点
          p=q->rchild;               //遍历右子树
        }
    }                                //while
    return OK;
} 
    

5) 层次遍历

(用队列的思想实现遍历)

【基本思想】

  1. 根结点进队;
  2. 队不空时循环。从队列中列出一个结点*p,:若有左孩子结点,将左孩子入队;若有右孩子结点,则将右孩子入队。

【定义】?

typedef struct{
     BTNode data[MaxSize];   //存放队中元素
     int front,rear;         //队头和队尾指针
}SqQueue;                    //顺序循环队列类型

二叉树层次遍历算法:?

void LecelOrder(BTNode *b){
     BTNode *p;    SqQueue *qu;
     InitQueue(qu);   
     

2.4 二叉树遍历的应用

1)建立二叉链表

先序遍历序列建立二叉树的二叉链表。? ? ? ? ? ? ? ? ??

?【例】已知先序序列为:ABCDEF:

? ABC##DE#G##F###

Status CreateBiTree(BiTree &T){
   cin>>ch;
   if(ch=="#") T=NULL;
   else {
         if (!(T=(BiTNode*)malloc(sizeof(BiTNode))))
         T=new BiTNode;       //
         T->data=ch;
         CtrateBiTree(T->lchild);   //
         CtrateBiTree(T->rchild);   //
        }
}

2)复制二叉树

【算法步骤】

如果是空树,递归结束;否则:

  1. 申请一个新结点空间,复制根节点。
  2. 递归复制左子树。
  3. 递归复制右子树。
Status CreateBiTree(BiTree &T){
   

3)计算二叉树深度

【算法步骤】

如果是空树,深度为0,递归结束,否则:

  1. 递归计算左子树的深度m;
  2. 递归计算右子树的深度n;
  3. 如果m大于n,二叉树的深度为m+1,否则为n+1。
Status CreateBiTree(BiTree &T){
   

4)计算二叉树结点总数

【算法步骤】

  1. 如果是空树,则结点个数为0;
  2. 否则,结点个数为左子树的结点个数+右子树的结点个数+1
Status NodeCount(BiTree &T){
   if(T=NULL)
      return 0;                           //空树结点为0
   else
       return NodeCount(T->lchild)+
              NodeCount(T->rchild)+1;     //结点个数=左子树结点个数+右子树结点个数+1
}

2.5?线索二叉树

利用二叉链表中的空指针域:

  1. ?如果某结点左孩子为空,则将空的左孩子指针域改为指向其前驱;
  2. ?如果某结点右孩子为空,则将空的右孩子指针域改为指向其后继;

对二叉链表中每个结点增设两个标志域ltag rtag

  • ltag=0——lchild 指向该结点的左孩子
  • ltag=1——lchild 指向该结点的前驱
  • rtag=0——rchild 指向该结点的右孩子
  • rtag=1——rchild 指向该结点的后继

结点结构:

lchildltagdatartagtchild
typedef struct BiThrNode
{
   int data;
   int ltag,rtag;                      //定义左右标志
   struct  BiThrNode *lchild,rchild;   //定义左右孩子指针
} BiThrNode, * BiThrTree;

增设一个头结点:

  • ltag=0——lchild指向根节点,
  • rtag=1——rchild指向最后一个结点
  • 遍历序列里第一个结点的lc域和最后一个结点的rc域都指向头结点。

【图】?

3 树和森林

4 哈夫曼树

5 小结

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:59:14  更:2021-07-30 12:59:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 9:58:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计