树型结构2 AVL 森林与二叉树转化 二叉链表三种遍历
来源:互联网 发布:最新伪基站设备 淘宝 编辑:程序博客网 时间:2024/05/29 19:36
(4).AVL树:
使用了AVL树的插入,删除和查找。
数据结构即二叉树,多一个平衡因子(左右树深度的差值)的变元。
主要函数:void Lrotate(node * &p); //左旋
void Rrotate(node * &p); //右旋
void maintain(node * &p); //维护平衡
思路及原理:AVL树是一种平衡二叉树,其难点在于树平衡的维护。每当插入一个节点是,平衡因子会发生改变(原理是左右子树的深度差发生变化),当差值大于1时,需要平衡化。通过左旋,右旋,最后完成平衡。
(5).森林与二叉树的相互转化:
使用了邻接表存储结构,输入二叉树或森林实现森林向二叉树树的转化,和树向森林的转化。
结构如下:
typedef struct bnode//定义二叉树结点
{
char x;
struct bnode *lchild;
struct bnode *rchild;
} bnode;
typedef struct fnode //存储森林
{
int parent;
char x;
} fnode;
fnode f[30];
主要函数:
bnode * build(int i,int j,int u,int v,char pre[100],char in[100])//用递归方法建立二叉树
void ftob(bnode *b,int n); //森林转化为二叉树
void btof(bnode *b,int n); //二叉树转化为森林
思路及原理:先说二叉树转化为森林。链接所有二叉树的根节点和左右而知节点,再删去右儿子节点的连线和深度大于1的左儿子连线,即可得到森林。森林转化为二叉树的过程与之相对,通过遍历删连接线即可。
(6).前序/后序/层序遍历
使用了二叉链表存储结构,输入一个森林,进行三种遍历,输出遍历结果
结构如下:
struct FNode {
FNode *next;
FNode *parent;
FNode *child;
int weight;
int id;
};
思路及原理:其实就是左儿子右兄弟表示出来后的遍历算法。从某个节点为起始开始进行栈操作得到遍历即可。
AVL树的插入、删除、查找/* author:yjc time:2014/3/21 title:AVL tree*/#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#define oo 0x7FFFFFFFusing namespace std;template <typename T>class AVL{private: class node { public: node *l,*r; int h,size; T dat; node() : l(0) ,r(0), h(1),size(0) {}; node(T tdat) : dat(tdat),l(0),r(0), h(1),size(1) {}; //得到平衡因子 int geth() { if(!this) return 0; else return h; } //得到子树深度 int getsize() { if(!this) return 0; else return size; } //更新平衡后的树的高度 void update() { if(this) { h = max(l->geth() ,r->geth()) + 1; size = l->getsize() + r->getsize() + 1; } } }*root; //左旋 void Lrotate(node * &p) { node * t = p->r->l; p->r->l = p; p= p->r; p->l->r =t; p->l->update(); p->update(); } //右旋 void Rrotate(node * &p) { node * t = p->l->r; p->l->r = p; p= p->l; p->r->l = t; p->r->update(); p->update(); } //维持平衡的操作 void maintain(node * &p) { int lh ,rh; if(p->l->geth() > p->r->geth() + 1) // To balance the left tree { lh = p->l->l->geth(); rh = p->l->r->geth(); if(lh >= rh) Rrotate(p); else { Lrotate(p->l); Rrotate(p); } } if(p->r->geth() > p->l->geth() + 1 ) // To balance the right tree { lh = p->r->l->geth(); rh = p->r->r->geth(); if(rh >= lh) Lrotate(p); else { Rrotate(p->r); Lrotate(p); } } } //插入操作 void insert(node * & p, T dat) { if(!p) { p = new node(dat); return; } if(dat <= p->dat) insert(p->l,dat); else insert(p->r,dat); maintain(p); p->update(); } //删除操作 void erase(node * & p, T dat) { if(!p) return; if(p ->dat == dat) { if(p->l && p->r) { node * t = p->r; while(t->l) t = t->l; p->dat = t->dat; erase(p->r,t->dat); maintain(p); } else if(p->l) { p->dat = p->l->dat; p->l = 0; } else if(p->r) { p->dat = p->r->dat; p->r = 0; } else p = 0; p->update(); return; } else if(dat < p->dat) erase(p->l,dat); else erase(p->r,dat); maintain(p); p->update(); } //查找操作 bool findk(node * p, int k) { if(!p) return false; else if(k == p->dat) return true; else if(k <= p->dat) return findk(p->l,k); else if(k > p->dat) return findk(p->r,k); }public: AVL() : root(0) {}; void insert(T dat) { insert(root, dat); } void erase(T dat) { erase(root, dat); } bool findk(int k) { if(findk(root, k)) return true; return false; } //清空操作 void clear(node * p) { if(!p) return; clear(p->l); clear(p->r); delete p; } //判空 bool empty() { return (root->getsize() == 0); } int size() { return root->getsize(); } //得到根节点 node* getroot() { return root; } //打印操作,中序遍历 void print(node *p){ if(p!=NULL){ print(p->l); printf("%d ",p->dat); print(p->r); } }};int main(){ int n,dat; char cmd; printf("请输入操作总数:"); while(scanf("%d",&n) == 1) { AVL <int> avl; printf("操作类型和操作数(操作类型中'I'表示插入,'F'表查找,'D'表删除):"); while(n--) { scanf(" %c %d",&cmd,&dat); if(cmd == 'I') { int tmp= avl.findk(dat); if(tmp==1){ printf("The num is already in the AVL_tree\n"); continue; } avl.insert(dat); printf("After adding: root=%d \n",avl.getroot()->dat); printf("The Tree Searched by In order: "); avl.print(avl.getroot()); cout << endl; } else if(cmd == 'F') { int tmp = avl.findk(dat); printf("%s\n", tmp == 0 ? "No" : "Yes"); } else if(cmd == 'D') { int tmp = avl.findk(dat); if(tmp == 1){ avl.erase(dat); printf("after Deleting: root=%d \n",avl.getroot()->dat); printf("The Tree Searched by In order: "); avl.print(avl.getroot()); cout << endl; } else{ printf("Not found the node.\n"); continue; } } } avl.clear(avl.getroot()); } return 0;}/*10I 2I 8I 6I 4F 6D 6I 1000F 93D 1000D 2*/邻接表实现树与森林的转换/* author:yjc time:2014/3/22 title:邻接表存储实现森林与树的转换*/#include <stdio.h>#include <stdlib.h>#include <conio.h>typedef struct bnode//定义二叉树结点{ char x; struct bnode *lchild; struct bnode *rchild;} bnode;typedef struct fnode{ int parent; char x;} fnode;fnode f[30];bnode *BuildNode()//建立新结点{ bnode *p; p=(bnode *)malloc(sizeof(bnode)); p->lchild=NULL; p->rchild=NULL; return p;}bnode * build(int i,int j,int u,int v,char pre[100],char in[100])//用递归方法建立二叉树{ int k,l; bnode *head,*s; head=NULL; if(i<=j)//先根序列已结束 { head=BuildNode();//建立根节点 head->x=pre[i]; k=u; while(in[k]!=pre[i]) { k++;//找到中序的根节点 } l=i+k-u;//l为左子树中最右下节点在前序序列中的位置 if(k==u)//左子树为空 { head->lchild=NULL; } else { s=build(i+1,l,u,k-1,pre,in);//构造左子树 head->lchild=s; } if(k==v)//右子树为空 { head->rchild=NULL; } else { s=build(l+1,j,k+1,v,pre,in);//构造右子树 head->rchild=s; } } return head;}void ShowTree(bnode *p)//输出创建的二叉树{ if(p!=NULL) { printf("("); printf("%c",p->x); printf(","); ShowTree(p->lchild); printf(","); ShowTree(p->rchild); printf(")"); } else printf("#");}void ftob(bnode *b,int n){ int a,i=1,j,k; bnode *d[30]; b=BuildNode(); b->x=f[i].x; d[i]=b; i++; while(f[i].parent==0) { b->rchild=BuildNode(); b=b->rchild; b->x=f[i].x; d[i]=b; i++; } while(i<=n) { k=f[i].parent; b=BuildNode(); b->x=f[i].x; d[k]->lchild=b; d[i]=b; i++; if(i>n) { break; } while(f[i].parent==k) { b->rchild=BuildNode(); b=b->rchild; b->x=f[i].x; d[i]=b; i++; if(i>n) { break; } } }}void btof(bnode *b,int n){ int x=1,num,k,i; bnode *d[30],*p; if(b==NULL) { return ; } else { while(b!=NULL) { f[x].x=b->x; f[x].parent=0; d[x]=b; x++; b=b->rchild; } num=x; k=1; while(x<=n) { for(i=k; i<num; i++) { p=d[i]->lchild; while(p!=NULL) { f[x].x=p->x; f[x].parent=i; d[x]=p; x++; p=p->rchild; } } k=i; num=x; } }}int main(){ int c,num,i; char pre[30],in[30]; bnode *p; printf("请输入要创建树的结点数:"); scanf("%d",&num); printf("请输入前序序列:"); scanf("%s",pre); printf("请输入中序序列:"); scanf("%s",in); p=build(0,num-1,0,num-1,pre,in); btof(p,num); ShowTree(p); getch(); puts("\n***********************MENU*********************\n"); puts("1.二叉树转化为森林\n"); puts("2.森林转化为二叉树\n"); puts("3.结束转化\n"); puts("************************************************\n"); while(1) { printf("请输入你的选择(1-3): "); while(1) { scanf("%d",&c); if(c<1||c>3) { printf("出错了!请再次输入(1-3): "); } else break; } switch(c) { case 1: btof(p,num); for(i=1; i<=num; i++) { printf("(%d)%d.%c\n",f[i].parent,i,f[i].x); } break; case 2: ftob(p,num); ShowTree(p); printf("\n"); break; case 3: exit(0); break; } } return 0;}/*5ABDCEBDAEC A / \ B C \ / D C*/二叉链表存储结构实现树的前序后序层序遍历/* author:yjc time:2014/3/22 title:森林的遍历*/#include <cstdio>#include <cstring>#include <iostream>#include <queue>using namespace std;#define maxn 1000struct FNode { FNode *next; FNode *parent; FNode *child; int weight; int id;};struct BNode { BNode *parent; BNode *lc,*rc; int weight; int id; BNode() { parent=lc=rc=NULL; }};FNode F[maxn];void InitF(int n) { for(int i=1; i<=n; i++) { F[i].id=i; F[i].child=F[i].child=F[i].next=NULL; }}BNode *Rt;void Make1(BNode *rt,int x) { FNode *tmp=F[x].child; BNode *brt=rt; if(tmp!=NULL) { brt->lc=new BNode; brt->lc->id=tmp->id; brt->lc->parent=brt; Make1(brt->lc,brt->lc->id); tmp=tmp->next; brt=brt->lc; while(tmp!=NULL) { brt->rc=new BNode; brt->rc->id=tmp->id; brt->rc->parent=brt; Make1(brt->rc,tmp->id); tmp=tmp->next; brt=brt->rc; } }}void Print1(BNode *rt) { if(rt==NULL) return; Print1(rt->lc); printf("id:%d lc:%d rc:%d\n",rt->id,rt->lc==NULL? 0:rt->lc->id,rt->rc==NULL? 0:rt->rc->id); Print1(rt->rc);}char str[999];BNode *PreBuild(BNode *rt){ int tmp; cin>>tmp; if(tmp) { rt=new BNode; rt->id=tmp; rt->lc=PreBuild(rt->lc); rt->rc=PreBuild(rt->rc); } else rt=NULL; return rt;}void Make2(BNode *rt,BNode *pi){ if(rt==NULL) return; printf("%d is %d's child.\n",rt->id,pi==NULL? 0:pi->id); if(rt->lc!=NULL){ Make2(rt->lc,rt); } Make2(rt->rc,pi);}void PreP(BNode *rt){ if(rt==NULL) return; printf("%d ",rt->id); PreP(rt->lc); PreP(rt->rc);}void PostP(BNode *rt){ if(rt==NULL) return; PostP(rt->lc); PostP(rt->rc); printf("%d ",rt->id);}void LevelP(BNode *rt){ queue<BNode*> q; q.push(rt); while(!q.empty()){ BNode *cur=q.front(); q.pop(); printf("%d ",cur->id); if(cur->lc!=NULL) q.push(cur->lc); if(cur->rc!=NULL) q.push(cur->rc); }}int main() { printf("请输入选项(1:以森林形式输入 2:以二叉树形式输入):"); int cmd; scanf("%d",&cmd); if(cmd==1) { int n,m; printf("请输入顶点数:"); scanf("%d",&n); InitF(n); printf("请输入关系数:"); scanf("%d",&m); int a,b; for(int i=1; i<=m; i++) { cin>>a>>b; F[a].parent=&F[b]; FNode *tmp=F[b].child; if(tmp==NULL) F[b].child=&F[a]; else { while(tmp->next!=NULL){ tmp=tmp->next; } tmp->next=&F[a]; F[a].next=NULL; } } Rt=NULL; BNode *tmp=Rt; for(int i=1; i<=n; i++) { if(F[i].parent==NULL) { if(Rt==NULL) { Rt=new BNode; Rt->id=i; Rt->parent=NULL; Rt->lc=NULL; Rt->rc=NULL; tmp=Rt; } else { tmp->rc=new BNode; tmp->rc->parent=tmp; tmp=tmp->rc; tmp->id=i; tmp->lc=tmp->rc=NULL; } Make1(tmp,i); } } //Print1(Rt); }else if(cmd==2){ printf("输入二叉的前序遍历序列(空节点用'0'表示): "); Rt=PreBuild(Rt); } printf("前序遍历:\n"); PreP(Rt); puts(""); printf("后序遍历\n"); PostP(Rt); puts(""); printf("层序遍历\n"); LevelP(Rt); puts(""); return 0;}/* 1 / \ 2 3 \ / 4 512040035000 1 / \ 2 3322 13 1 1------5 / \ / 2 3 6 \ 4652 13 14 21 56 5*/
- 树型结构2 AVL 森林与二叉树转化 二叉链表三种遍历
- 二叉树与森林的转化
- 树、森林与二叉树的转化理解
- 树、森林与二叉树相互转化原理图
- 二叉树、树、森林之间转化
- 树、森林转化为二叉树
- 树、二叉树、森林之间的转化
- 二叉树、树、森林之间的转化
- C++森林转化为二叉树代码
- 森林和二叉树的转化
- 树、森林与二叉树的转换及遍历
- 树、森林与二叉树
- 树、森林与二叉树(树的存储结构(树的孩子兄弟链表应用举例),树转换为二叉树,二叉树转换成树和森林,树和森林的遍历)
- 树,二叉树,森林各种遍历总结:
- 关于二叉树的结构与遍历
- 【LeetCode101-110】二叉树对称及存储,前序中序遍历生成二叉树,中序后序生成二叉树,数组转化为AVL平衡树,判断二叉树是否平衡
- 二叉树--AVL树
- AVL 平衡二叉树
- 程序员怎么才能提高代码编写速度?
- Hibernate二级缓存的配置
- 内存和指针泄露常见问题
- Coursera公开课Functional Programming Principles in Scala习题解答:Week 1
- JavaScript省市联动菜单
- 树型结构2 AVL 森林与二叉树转化 二叉链表三种遍历
- maven教程之三仓库
- flush="true" 的含义
- 2014.04
- 动态链接库之延迟绑定探究
- maven教程之三仓库(新)
- 设计模式
- 强大的 java 分页器
- 04-01递归原理分析_分析方法调用