树型结构2 AVL 森林与二叉树转化 二叉链表三种遍历

(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 0x7FFFFFFF

using 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;
}

/*
10
I 2
I 8
I 6
I 4
F 6
D 6
I 1000
F 93
D 1000
D 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;
}

/*
5
ABDCE
BDAEC
    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 1000
struct 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 5
1
2
0
4
0
0
3
5
0
0
0


    1
   / \
  2   3
3
2
2 1
3 1

    1------5
   / \    /
  2   3  6
   \
    4

6
5
2 1
3 1
4 2
1 5
6 5

*/


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值