树型结构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*/


0 0