提高篇--数据结构专题3

树与二叉树

树的定义与性质

  - 没有结点的树,称为空树
  - 树的层次
  从根结点开始算
  根结点为第一层
  - 结点的子树棵数称为结点的度,树中结点最大的度称为树的度
  - 一条边连接两个结点,树中不存在环
  对n个结点的树,边数是n-1
  - 叶子结点度为0
  - 树的深度,根结点深度为1,树的高度,叶子结点高度为1
  - 多棵树组合在一起称为森林

二叉树的递归定义

  二叉树的递归定义
  - 要么二叉树没有根结点,是一颗空树
  - 要么二叉树由根结点,左子树,右子树组成,且左子树和右子树都是二叉树


  1. 满二叉树
  每一层的结点个数都达到了当层能达到的最大结点数
  2. 完全二叉树
  除了最下面一层外,其余层的结点个数都达到了层能达到的最大结点数
  最下面一层只从左到右连续存在若干结点


  层次
  孩子结点,父亲结点,兄弟结点,祖先结点,子孙结点
  结点可以称为自身的祖先&子孙结点

二叉树的存储结构与基本操作

二叉树的存储结构

二叉树结点的查找,修改

二叉树的插入

二叉树的创建

二叉树存储结构图示

完全二叉树的存储结构

  对一棵完全二叉树,如果给它的所有结点按从上到下,从左到右的顺序编号[从1开始]
  对完全二叉树中的任何一个结点,设编号为x
  其左孩子的编号一定是2x,而右孩子的编号一定是2x+1

二叉树的遍历

  先序遍历,中序遍历,后序遍历,层次遍历

先序遍历

先序遍历的实现

中序遍历

中序遍历的实现

后序遍历

后序遍历的实现

性质

  给定前/后序+中序可恢复二叉树

层次遍历

二叉树的静态实现

  所谓静态二叉链表指,节点的左右指针域使用int型代替,表示左右子树的根节点在数组中的下标

树的遍历

树的静态写法

树的先根遍历

树的层次遍历

从树的遍历看DFS与BFS

深度优先搜索与先根遍历

  对所有合法的DFS求解过程
  可把它画成树的形式
  对这棵树的DFS遍历过程就是树的先根遍历的过程

广度优先搜索与层次遍历

二叉查找树

二叉查找树的定义

  二叉查找树,又称为排序二叉树,二叉搜索树,二叉排序树
  二叉查找树的递归定义
  - 要么二叉查找树是一棵空树
  - 要么二叉查找树由根结点,左子树,右子树组成.其中左子树和右子树都是二叉查找树,且左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有节点的数据域均大于根结点的数据域

二叉查找树的基本操作

  二叉查找树的基本操作有查找,插入,建树,删除

查找

插入

二叉树的建立

二叉查找树的删除

  把以二叉查找树中比结点权值小的最大结点称为该结点的前驱
  把比结点权值大的最小结点称为该结点的后继

二叉查找树的性质

  对二叉查找树进行中序遍历,遍历的结果是有序的

平衡二叉树

平衡二叉树的定义

平衡二叉树的基本操作

查找

并查集

并查集的定义

  并查集是一种维护集合的数据结构
  并查集下面操作
  - 合并
  合并两个集合
  - 查找
  判断两个元素是否在一个集合

  int father[N];
  father[i]表示元素i的父亲节点
  父亲节点本身也是这个集合内的元素[1<=i<=N]
  如果father[i]=i,则说明元素i是该集合的根结点
  对同一个集合来说只存在一个根结点,且将其作为所属集合的标识

并查集的基本操作

  并查集的使用,需先初始化father数组
  再根据需要进行查找或合并的操作

初始化

  开始时,每个元素都是独立的一个集合
  for(int i = 1; i <= N; i++)
  {
        father[i] = i;
  }

查找

  规定同一个集合中只存在一个根节点
  因此,查找操作就是对给定的结点寻找其根节点的过程
  int findFather(int x)
  {
        if(x == father[x])
              return x;
        else
              return findFather(father[x]);
  }

合并

  合并是指把两个集合合并为一个集合
  合并的过程一般是把一个集合的根结点的父亲指向另一个集合的根节点
  - 对于给定的两个元素a,b
  判断它们是否属于同一个集合
  - 合并两个集合
  在1步获得两个元素的根节点faA, faB
  只需把其中一个的父亲结点指向另一个结点
  例father[faA]=faB或反过来
  void Union(int a, int b)
  {
        int faA = findFather(a);
        int faB = findFather(b);
        if(faA != faB)
        {
              father[faA] = faB;
        }
  }


  并查集产生的每一个集合都是一棵树

路径压缩

  考虑一种情况,
  题目给出的元素数量很多且形成一条链,则这个查找函数的效率会低.
  如何优化查询操作?
  由于findFather函数的目的就是查找根结点,
  转换的过程可概括为如下两个步骤:
  - 按原先的写法获得x的根结点r
  - 重新从x开始走一遍寻找根结点的过程,把路径上经过的所有结点的父亲全部改为根结点r
  int findFather(int x)
  {
        int a = x;
        while(x != father[x])
        {
              x = father[x];
        }


        while(a != father[a])
        {      
              int z = a;
              a = father[a];
              father[z] = x;
        }      
        
        return x;
  }

堆的定义与基本操作

  堆是一颗完全二叉树
  树中每个结点的值都不小于[或不大于]其左右孩子结点的值
  如父亲结点的值大于或等于孩子结点的值,称为大顶堆
  如父亲结点的值小于或等于孩子结点的值,称为小顶堆

哈夫曼树

哈夫曼树

哈夫曼编码

原文地址:https://www.cnblogs.com/raindayinrain/p/13642475.html