C++非线性结构

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1≤i<j)的双亲,则称该结点序列为从k1到kj的一条路径;路径长度
结点的层数:根结点层数为0,其余结点层数等于其双亲结点层数加1 。 树的深度(高度):即树中层数最大的结点的层数 。 结点的度数、树的度数:一个结点子女的个数称为该结点的“度数”。 树中度数最大的结点的度数叫做“树的度数” 。 树叶、分支结点:度数为0的结点叫做“树叶” ;度数大于0的结点叫做 “分 支结点”或“内结点” 。 有序树、无序树:若将树中每个结点的各个子树看成从左到右有序的, 则称该树为有序树;否则为无序树 。 森林:m(m≥0)棵互不相交的树的集合称为森林 。
二叉树的遍历
•先序遍历 •中序遍历 •后序遍历 •层次遍历
访问根结点,先序遍历左子树,先序遍历右子树。
中序遍历左子树,访问根结点,中序遍历右子树。 后序遍历左子树,后序遍历右子树,访问根结点。 按层数由小到大、同一层从左到右顺序依次访问二叉树的各个结点
先序访问序列 :ABDGECF 中序访问序列 :DGBEAFC 后序访问序列 :GDEBFCA 层次访问序列 :ABCDEFG
先将森林中的每一棵树变为二叉树,然后将各二叉树的根结点看成兄弟, 用线把它们连到一起,经整理后可得到相应的二叉树。
树、森林与二叉树的转换 (续)
2.二叉树到树、森林的转换
若结点x是其双亲y的左子女,则把x的右子女、右子女的右子女……都 与y连线,最后去掉所有双亲到右子女的连线。
哈夫曼树基本概念
1.扩充二叉树和带权路径长度:
假设{W0,W1,…,Wn-1}是n个实数的集合,其中Wi≥0(0≤i≤n-1 )。若T是一棵有n个叶结点的二叉树,而且将W0,W1,…,Wn-1分别赋给T的n 个叶结点作为它们的权,则称T是权值为W0,W1,…,Wn-1的扩充二叉树。带有权 值的叶结点叫做扩充二叉树的外结点,其余的分支结点叫做内结点。 一个有n个外结点的扩充二叉树的带权路径长度(WPL)为: WPL=
}
二叉排序树类的成员函数
树、森林与二叉树的转换
1.树、森林到二叉树的转换 将树转换成二叉树:
不是拓扑 等价转换 ①在所有的兄弟之间加一条连线; ②对每个结点,除了保留与最左边子女的连线外,去掉与其他子女连线; ③将保留下来的边作为左子树的边,兄弟间的连线作为右子树的边。
将一个森林转换成二叉树:
3.哈夫曼树
利用哈夫曼提出的方法构造出的最优二叉树称为哈夫曼树。
4.哈夫曼树构造方法
①由给定的n个权值{W0,W1,…,Wn-1}构造含有n棵扩充二叉树的 森林F,森林中的每棵二叉树都只有一个根结点,且每个根结点都取一个各不相同 的Wi作为权值; ②用森林F中根结点的权值为最小和次小的两棵二叉树作为左、右子树构 造出一棵新的二叉树,并将新二叉树的根结点的权值取为左、右子树根结点权值之 和; ③从森林F中删去作为新二叉树左、右子树的两棵二叉树,将新构造的二 叉树加入到森林F中; ④重复步骤②和③,直到F中仅剩下一棵二叉树为止。
二叉树的性质
1. 二叉树的性质
性质1 性质2 性质3
二叉树第i层上的结点数目最多为2i(i≥0)。 深度为k的二叉树至多有2k+1-1个结点(k≥0)。
在任意一棵二叉树中,若终端结点的个数为n0、度数为2的结点 的个数为n2,则n0=n2+1。
2. 两种特殊的二叉树
满二叉树
完全二叉树
完全二叉树性质
二叉树的基本概念
1.二叉树的定义
二叉树是n(n≥0)个结点的有限集合。它或者是空集
(n=0),或者由一个根结点及两棵互不相交的、分别称为 这个根的左子树和右子树的二叉树组成。
2. 二叉树五种基本形态
Φ
3.树和二叉树的差别

二叉树的子树有左、右之分,树的子树是相同的。 二叉树可以是空,而树不能为空。
二叉排序树类
二叉排序树:一种特殊的二叉树,其特点是:左子树上所有结点
的值均小于其双亲结点的值,右子树上所有结点的值均大于或等于其 双亲结点的值。
template <typename T> class BinTree{ public: BinTree():root(NULL){} //构造一棵空树 ~BinTree(){Destroy(root);} //析构函数 void insertNode(T val){ //向二叉树插入值为val的结点 insertNode(root,val); } void PreOrder(){PreOrder(root);} //前序遍历二叉树 void InOrder(){InOrder(root);} //中序遍历二叉树 void PostOrder(){PostOrder(root);} //后序遍历二叉树 void LevelOrder(){LeverOrder(root);} //层次遍历二叉树 private: Node<T> *root; //根结点指针 void insertNode(Node<T> *&t,T val); //向t指向的二叉树中插入结点 void PreOrder(Node<T> *t); //前序遍历t指向的二叉树 void InOrder(Node<T> *t); //中序遍历t指向的二叉树 void PostOrder(Node<T> *t); //后序遍历t指向的二叉树 void LeverOrder(Node<T> *t); //层次遍历t指向的二叉树 void Destroy(Node<T> *t); //删除二叉树 };
Wl
i 0 i
n 1
i
其中,Wi为外结点i所带的权值;li为从根结点到外结点i的路径长度。
(a) WPL=40
(b) WPL=50
(c) WPL=38
哈夫曼树基本概念 (续)
2.最优二叉树
通常,把权值取为{W0,W1,…,Wn-1}的所有扩充二叉树中WPL为 最小的扩充二叉树称为最优二叉树。
第三部分 数据结构基础
第13 章 非线性结构
本章课件制作:靳展
本章内容(树形结构)
树的基本概念
二叉树的基本概念和性质
二叉树的存储结构 二叉树的遍历 C++中的二叉树类 树、森林与二叉树的转换 哈夫曼树
本章内容(图形结构)
图的概念
图的存储结构
图的遍历 图的生成树和最小生成树 最短路径 拓扑排序 关键路径
性质4 具有n个结点的完全二叉树的深度为 log2n 性质5 若对一棵有n个结点的完全二叉树,按自顶向下、同层由左到右顺序依次为
其每个结点从0开始编号,则对编号为i的结点ki(0≤i≤n-1)则有: ①若i>0,则ki双亲结点的编号为 (i-1)/2 ②若i=0,则ki是根结点。 ③若2i+1<n,则ki左子女结点的编号是2i+1,否则ki无左子女。 ④若2i+2<n,则ki右子女结点的编号为2i+2,否则ki无右子女。
有向图
如果一个图中的每条边都有方 向,称它为有向图。在有向图中,一 条有向边是由两个顶点组成的有序对。 有序对常用尖括号表示, 例如,<Vi,Vj>表示一条有向边 ,Vi是边的始点,Vj是边的终点。 <Vi,Vj>和< Vj ,Vi >表示的是两条不同的 边。
B:— ·· G:— — · L:·— ·· Q:— — ·— V:···—
C:— ·— · H:···· M:— — R:·— · W:·— —
D:— ·· I:·· N:— · S:···
E:· J:·— — — O:— — — T:—
X:— ··— Y:— ·— —
图的概念
图的定义
图用二重组G=(V,E)表示。其中,V是顶点的有穷非空集合;E是 V中顶点偶对(称为边)的有穷集合。 对一个给定的图G,用V(G)表示顶点集,用E(G)表示边集。
树的常用术语
双亲、子女、边:若结点y是结点x的一棵子树的根,则x称做y的“双亲
” ( y称做x的“子女”;有序对〈x,y〉称做从x到y的“边” 。
兄弟:具有同一双亲的结点 。 路径、路径长度:若树中存在着一个结点的序列k1k2……kj,使ki是ki+1
等于j-1,它是该路径所经过的边的数目 。
二叉树的存储结构
1. 顺序存储结构
对完全二叉树,利用性质5,将其所有结点按编号顺序依次存储在一维数组里。 对一般二叉树,需要加上一些并不存在的“虚结点”,转换为完全二叉树的形式 。
二叉树的存储结构
2. 链式存储结构
链接存储时结点的结构
template <typename T> template <typename T> class BinTree; //二叉树类BinTree的前视声明 template <typename T> class Node{ friend class BinTree<T>; //定义二叉树类BinTree为友元 public: Node():lchild(NULL),rchild(NULL){} //无参构造函数 Node(T val, Node<T> *lptr=NULL,Node<T> *rptr=NULL){ //带参构造函数 data=val; lchild=lptr; rchild=rptr; } T Getdata(){return data;} //返回结点数据 Node<T> *Left(){return lchild;} //返回左子女指针 Node<T> *Right(){return rchild;} //返回右子女指针 private: Node<T> *lchild,*rchild; T data;
} template <typename T> void BinTree<T>::PostOrder(Node<T> *t){ if(t!=NULL){ PostOrder(t->lchild); //后序遍历左子树 PostOrder(t->rchild); //后序遍历右子树 cout<<t->data<<" "; //访问根结点 } } template <typename T> void BinTree<T>::LeverOrder(Node<T> *t){ queue<Node<T>*> Q; //Q为队列,队列元素是二叉树结点的指针 Node<T> *p; if(t!=NULL){ Q.push(t); //根结点入队 while(!Q.empty()){ p=Q.front(); //取队头元素 Q.pop(); //删除队头元素 cout<<p->data<<" "; //访问结点 if(p->lchild!=NULL) Q.push(p->lchild); //左子女结点入队 if(p->rchild!=NULL) Q.push(p->rchild); //右子女结点入队 } } } template <typename T> void BinTree<T>::Destroy(Node<T> *t){ if(t!=NULL){ Destroy(t->lchild); Destroy(t->rchild); delete t; } }
wk.baidu.com
哈夫曼树的构造
哈夫曼树的应用
哈夫曼编码 例 设电文字符集为{a,b,c,d,e,f},各字符发送频率是{6,2,3,3,4,9},
利用哈夫曼树构造个字符的编码。 以字符发送频率为权值构造哈夫曼树
各字符的哈夫曼编码是
a:01
b:001
c:001 d:100
e:101
f:100
摩尔斯电码
A:· — F:· ·— · K:— ·— P:· — · — U:··— Z:— — ··
树的常用术语举例
森林

C是G的双亲,G是C的子女,〈C,G〉是从C到G的边。 B、C、D互为兄弟,而F和G不是兄弟 。 ADIN是从结点A到结点N的一条路径,其长度为3 。
层数为0的结点有A,层数为1的结点有B、C、D 。 树的深度为3 。 A、C、E、J的度数分别为3、1、2、0;树的度数为3 。 K、L、F、M、H、N、J都是树叶,其余结点都是分支结点 。
树的基本概念
1. 树的特点
树形结构是一类非常重要的 非线性结构,适合于描述数据元 素之间的层次关系
2. 树的定义
树是n(n>0)个数据元素的有限集合T。它满足以下两
个条件: ①有且仅有一个特定的称为根的元素; ②其余元素分为m(m≥0)个互不相交的有限集 合T1、T2、……、Tm,其中每个集合又都是一棵树并 称其为根的子树。
相关文档
最新文档