标签:操作 压缩 复制二叉树 let 编码表 不同 后序遍历 生成 空间
ADT Tree{
数据对象 D: D 是具有相同特性的数据元素的集合。 数据关系 R: 若 D 为空集,则称为空树; 若 D仅含一个数据元素,则 R 为空集,否则 R={H}, H 是如下二元关系: (1) 在D 中存在唯一的称为根的数据元素 root,它在关系 H 下无前驱; (2) 若D-{root} ≠空集,则存在D-{root}的一个划分D1 , D2, …,比(m>0), 对任意j≠k(1<=j, k<=m) 有 DjnDk =空集, 且对任意的 i (1<=i<=m), 唯一存在数据元素 xi∈Di, 有 <root, xi>∈H; (3) 对应于D-{root} 的划分,H-{ < root, x1 >, …, <root,xm> =有唯一的一个划分 H1 , H2 , …, Hm (m> 0), 对任意j≠k(l<=j<=m) 有HjnHk =空集, 且对任意 i(1<=i<=m), H1 是D1 上的二元关系,(D1, {Hi}) 是一棵符合本定义的树,称为根 root 的子树。 基本操作P: InitTree(&T) 操作结果:构造空树T。 DestroyTree (&T) 初始条件:树T存在。 操作结果:销毁树T。 CreateTree(&T,definition) 初始条件:definition 给出树 T 的定义。 操作结果:按 definition 构造树 T。 ClearTree(&T) 初始条件:树T存在。 操作结果:将树T清为空树。 TreeEmpty(T) 初始条件:树T存在。 操作结果:若 T 为空树,则返回 true, 否则 false。 TreeDepth(T) 初始条件:树T存在。 操作结果:返回T的深度。 Root(T) 初始条件:树T存在。 操作结果:返回T的根。 Value(T,cur_e) 初始条件:树 T 存在, cur_e是 T 中某个结点。 操作结果:返回 cur_e 的值。 Assign(T,cur_e,value) 初始条件:树 T 存在, cur_e是 T 中某个结点。 操作结果:结点 cur_e 赋值为 value。 Parent(T,cur_e); 初始条件:树 T 存在, cur_e是 T 中某个结点。 操作结果:若 cur_e是 T 的非根结点,则返回它的双亲,否则函数值为 “空”。 LeftChild(T,cur_e) 初始条件:树 T 存在, cur_e是 T 中某个结点。 操作结果:若 cur_e是T 的非叶子结点,则返回它的最左孩子,否则返回 “空”。 RightSibling(T,cur_e) 初始条件:树 T 存在, cur_e是 T 中某个结点。 操作结果:若 cur_e 有右兄弟,则返回它的右兄弟,否则函数值为 “空”。 InsertChild(&T,p,i,c) 初始条件:树 T 存在, p 指向 T 中某个结点, 1<=i<=p 所指结点的度+ 1, 非空树 c 与 T 不相交。 操作结果:插入c为T中 p 指结点的第l.棵子树。 DeleteChild(&T,p,i) 初始条件:树 T 存在, p 指向 T 中某个结点, 1<=i<=p 指结点的度。 操作结果:删除T中 p 所指结点的第l.棵子树。 TraverseTree(T) 初始条件:树T存在。 操作结果:按某种次序对T的每个结点访问一次。 ) ADT Tree
ADT BinaryTree{ 数据对象D: D是具有相同特性的数据元素的集合。 数据关系R: 若 D=<空集, 则 R=<空集, 称 BinaryTree 为空二叉树; 若 D-,6¢, 则 R={H}, H是如下二元关系: (1) 在 D 中存在唯一的称为根的数据元素 root, 它在关系 H 下无前驱; (2) 若 D-{root} -,6¢, 则存在 D-{root}={D1, Dr}, 且 D1 nDr=<空集; (3) 若 D1 ≠空集, 则 D1中存在唯一的元素x1, <root,x1>∈H, 且存在 D1 上的关系 H1 ∈H; 若Dr≠空集则 Dr中存在唯一的元素 Xr, <root , Xr> ∈H, 且存在 Dr上的关系 H工 仁 H; H={ <root, xi>, <root, xr>, Hi, Hr); (4) (D1, { H1}) 是一棵符合本定义的二叉树,称为根的左子树, (Dr, {Hr})是一棵符合本定义的二叉树,称为根的右子树。 基本操作 P: InitBiTree(&T) 操作结果:构造空二叉树T。 DestroyBiTree(&T) 初始条件:二叉树T存在。 操作结果:销毁二叉树T。 Crea七eBiTree(&T,definition) 初始条件; definition 给出二叉树 T的定义 。 操作结果:按 definition 构造二叉树 T。 ClearBiTree(&T) 初始条件:二叉树T存在。 操作结果:将二叉树T清为空树。 BiTreeEmpty(T) 初始条件:二叉树T存在。 操作结果:若 T 为空二叉树,则返回 true, 否则 false。 BiTreeDepth (T) 初始条件:二叉树T存在。 操作结果:返回T的深度。 Root(T) 初始条件:二叉树T存在。 操作结果:返回T的根 。 Value(T,e) 初始条件:二叉树 T存在,e是 T中某个结点。 操作结果:返回e的值。 Assign(T,&e,value) 初始条件:二叉树T存在, e是T中某个结点。 操作结果:结点 e 赋值为 value。 Parent(T,e) 初始条件:二叉树 T存在,e是 T中某个结点。 操作结果:若 e是T的非根结点,则返回它的双亲,否则返回 “空”。 LeftChild(T,e) 初始条件:二叉树T存在, e是T中某个结点。 操作结果:返回e的左孩子。若e 无左孩子,则返回 “空”。 RightChild(T,e) 初始条件:二叉树T存在,e是T中某个结点。 操作结果:返回 e的右孩子。若 e 无右孩子,则返回 “空”。 LeftSibling (T, e) 初始条件:二叉树T存在, e是T中某个结点。 操作结果:返回 e的左兄弟。若 e是T的左孩子或无左兄弟,则返回 “空”。 RightSibling(T,e) 初始条件:二叉树T存在,e是T中某个结点。 操作结果:返回 e的右兄弟。若 e是T的右孩子或无右兄弟,则返回 “空”。 InsertChild(&T,p,LR,c) 初始条件:二叉树 T存在, p 指向 T中某个结点,LR 为 0 或 1, 非空二叉树 c 与 T 不相交且右子树为空。 操作结果:根据 LR 为 0 或 1, 插入 c 为 T中p 所指结点的左或右子树。p 所指结点的原有左或右子树则成为 c的右子树。 DeleteChild (&T, p, LR) 初始条件:二叉树T存在,p指向T中某个结点,LR为0或1。 操作结果:根据LR为0或1, 删除T中p所指结点的左或右子树。 PreOrderTraverse(T} 初始条件:二叉树T存在。 操作结果:先序遍历T, 对每个结点访问一次。 InOrderTraverse(T) 初始条件:二叉树T存在。 操作结果:中序遍历T, 对每个结点访问一次。 PostOrderTraverse(T} 初始条件:二叉树T存在。 操作结果:后序遍历T, 对每个结点访问一次5 LevelOrderTraverse(T) 初始条件:二叉树T存在。 操作结果:层序遍历T, 对每个结点访问一次。 } ADT BinaryTree
//-----二叉树的顺序存储表示----- #define MAXTSIZE 100 //二叉树的最大结点数 typedef TElemType SqBiTree [MAXTSIZE]; //0 号单元存储根结点 SqBi Tree bt;
//- - - - -二叉树的二叉链表存储表示- ---- typedef struct BiTNode{ TElemType data; //结点数据域 struct BiTNode *lchild,*rchild; //左右孩子指针 ) BiTNode,*BiTree;
void InOrderTraverse{BiTree T) {//中序遍历二叉树T的递归算法 if(T)//若二叉树非空 { InOrderTraverse {T-> lchild) ; / /中序遍历左子树 cout<<T->data; II访问根结点 InOrderTraverse {T-> rchild); //中序遍历右子树 } }
void InOrderTraverse(BiTree T) {//中序遍历二叉树T的非递归算法 InitStack(S);p=T; q=new BiTNode; while (p || ! StackEmpty (S)) { if(p) //p非空 { Push(S,p);//根指针进栈 p=p-> lchild; //根指针进栈, 遍历左子树 } else { Pop (S, q);//退栈 cout<<q->data;//访问根结点 p=q-> rchild;//遍历右子树 } }//while }
void CreateBiTree(BiTree &T) {//按先序次序输入二叉树中结点的值( 一个字符), 创建二叉链表表示的二叉树T cin>>ch; if(ch== ‘#‘) T=NULL; //递归结束, 建空树 else {//递归创建二叉树 T=new BiTNode; //生成根结点 T-> data=ch; //根结点数据域置为 ch CreateBiTree (T-> lchild); //递归创建左子树 CreateBiTree (T-> rchild); //递归创建右子树 } //else }
void Copy(BiTree T,BiTree &NewT) {//复制一棵和T完全相同的二叉树 if(T==NULL) //如果是空树, 递归结束 { NewT=NULL; return; } else { NewT=new BiTNode; NewT-> da ta=T->data; //复制根结点 Copy (T-> lchild, NewT-> lchild); //递归复制左子树 Copy (T-> rchild, NewT-> rchild); //递归复制右子树 }//else }
int Depth(BiTree T) {//计算二叉树T的深度 if(T==NULL) return 0; //如果是空树,深度为0, 递归结束 else { m=Depth {T->lchild); //递归计算左子树的深度记为m n=Depth {T->rchild) ; //递归计算右子树的深度记为n if{m>n) return{m+1); //二叉树的深度为m与n的较大者加1 else return(n+1); } }
int NodeCount(BiTree T) {//统计二叉树T中结点的个数 if (T==NULL) return O; //如果是空树,则结点个数为0, 递归结束 else return NodeCount (T->lchild) +Node Count (T->rchild) + 1; //否则结点个数为左子树的结点个数+右子树的结点个数+1 }
//- - - - -二叉树的二叉线索存储表示- ---- typedef struct BiThrNode { TElemType data; struct BiThrNode *lchild,*rchild; //左右孩子指针 int LTag,RTag;//左右标志 ) BiThrNode,*BiThrTree;
void InThreading(BiThrTree p) { //pre是全局变址,初始化时其右孩子指针为空,便于在树的最左点开始 建线索 if(p) InThreading (p-> lchild) ;//左子树递归线索化 if (! p-> lchild) //p的左孩子为空 { p->LTa_g=1; //给p加上左线索 p-> lchild=pre; //p的左孩子指针指向pre (前驱) }//if else p->LTag=O; //pre的右孩子为空 if { ! pre-> rchild) { pre-> RTag=1; //给pre加上右线索 pre-> rchld=p; //pre的右孩子指针指向p (后继) }//if else p->RTag=0; pre=p; //保持pre指向p的前驱 InThrending (p-> rchild) ; //右子树递归线索化 } }
void InOrderThreading(BiThrTree &Thrt,BiThrTree T) {// 中序遍历二叉树 T, 并将其中序线索化,Thrt指向头结点 Thrt=new Bi ThrNode;//建头结点 Thrt->LTag=O; // 头结点有左孩子, 若树非空,则其左孩子为树 根 Thrt-> RTag=l; // 头结点的右孩子指针为 右线索 Thrt-> rchild=Thrt; //初始化时右指针指向自己 if (! T) Thrt-> lchild=Thrt; //若树为空,则左指针也指向自己 else { Thrt-> lchild=T; pre=Thrt; //头结点的左孩子指向根,pre 初值指向头结点 InThreading(T); //调用算法5. 7, 对以T为 根的二叉树进行中序线索化 pre-> rchild=Thrt; //算法5.7结束后,pre为 最右结点,pre的右线索指向头结点 pre-> RTag=1; Thrt- > rchild=pre; //头结点的右线索指向 pre } }
void InOrderTraverse_Thr(BiThrTree T) {//T指向头结点,头结点的左链lchild指向根结点, 可参见线索化算法5.8。 //中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出 p=T-> lchild; //p指向根结点 while(p!=T)//空树或遍历结束时,p==T { while (p-> LTag==O) p=p-> lchild; //沿左孩子向下 cout<<p->data;II访问其左子树为空的结点 while (p-> RTag==l&&p-> rchild ! =T) { p=p-> rchild; cout<<p-> data; //沿右线索访问后继结点 } p=p-> rchild;//转向p的右子树 } }
//- - - - - -树的二叉链表(孩子-兄弟)存储表示----- typedef struct CSNode{ ElemType data; struct CSNode *firstchild, *ne·xtsibling; ) CSNode,*CSTree;
//- - - - -哈夫曼树的存储表示 --- - - .- typedef struct{ int weight; //结点的权值 int parent,lchild,rchild; ) HTNode,*HuffmanTree; //结点的双亲、左孩子、右孩子的下标 //动态分配数组存储哈夫曼树
void CreateHuffmanTree(HuffmanTree &HT,int n) {//构造哈夫曼树 HT if(n<=l) return; m=2*n-l; HT=new HTNode[m+1); //0 号单元未用,所以需要动态分配 m+l 个单元, HT[m)表示根结点 for(i=1;i<=m;++i) //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0 {HT[i] .parent=O;HT[i] .lchild=O;HT[i] .rchild=O;} for(i=1;i<=n;++i} //输人前 n 个单元中叶子结点的权值 cin>>HT[i] .weight; /*- - -初始化工作结束, 下面开始创建哈夫曼树- - - */ for (i=n+1; i<=m; ++i} {//通过 n-1 次的选择、删除 、 合并来创建哈夫曼树 Select (HT, i-1, sl, s2); //在 HT[k] (1<=k<=i-1)中选择两个其双亲域为0 且权值最小的结点,并返回它们在 HT 中的序号 sl和 s2 HT[sl] .parent=i;HT[s2] .parent=i; //得到新结点 i, 从森林中删除sl, s2, 将sl和s2 的双亲域由 0改为l. HT[i] .lchild=sl;HT [i]. rchild=s2; //s1, s2分别作为i的左右孩子 HT[i] .weight=HT[sl] .weight+HT[s2] .weight; //i的权值为左右孩子权值之和 }/ /for }
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n) //I从叶子到根逆向求每个字符的哈夫曼编码, 存储在编码表HC中 HC=new char* [n+1]; //分配存储n个字符编码的编码表空间 cd=new char [n]; //分配临时存放每个字符编码的动态数组空间 cd[n-1]=‘\0‘; //编码结束符 for(i=1;i<=n;++i) //逐个字符求哈夫曼编码 { start=n-1; //start 开始时指向最后, 即编码结束符位置 c=i; f=HT [i] .parent; / /f指向结点c的双亲结点 while(f!=0) //从叶子结点开始向上回溯, 直到根结点 { --start; //回溯一次start向前指一个位置 if(HT[f] .lchild==c) cd[start]=‘0‘; //结点c是f的左孩子, 则生成代码0 else cd[start]=‘1‘; //结点c是f的右孩子, 则生成代码1 c=f;f=HT[f] .parent; //继续向上回溯 }//求出第l.个字符的编码 HC[i]=new char[n-start]; //为第i个字符编码分配空间 strcpy(HC[i],&cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中 } delete cd; //释放临时空间 }
标签:操作 压缩 复制二叉树 let 编码表 不同 后序遍历 生成 空间
原文地址:https://www.cnblogs.com/stdeng/p/12934239.html