树与二叉树

树的存储结构分为三种,分别是双亲顺序存储结构,孩子链式存储结构,孩子兄弟链式存储结构,代码如下:

#define ElemType char
//双亲顺序存储结构
//结点中储存的是双亲的信息
#define MAXSIZE 100
typedef struct 
{
    ElemType data[MAXSIZE];
    int parent;
}

//孩子链式存储结构
//节点中存储的是孩子的信息
#define MAXSONS 3
typedef struct node
{
    ElemType data;
    struct node sons[MAXSONS];
}TSonNode;

//孩子兄弟存储结构
//结点中存储的是左孩子和兄弟的信息
typedef struct tnode
{
    ElemType data;
    struct tnode *vp;//指向孩子结点
    struct tnode *hp;//指向兄弟结点
}TSBNode;   

二叉树的存储结构分为两种,顺序存储结构和链式存储结构,顺序存储结构也就是数组存储

#define ElemType char
//二叉树的顺序存储
#define MAXSIZE 100
typedef struct
{
    ElemType data;
}SqTree[MAXSIZE];

//二叉树的链式存储结构
typedef struct BTNode
{
    ElemType data;
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode;

二叉树的顺序存储结构中,若结点的下标为i,则其左孩子的下标为2*i,右孩子的坐标为2*i+1,父母的结点为i/2,顺序存储结构占用的空间比较大,因为不存在的结点都要用一个固定符号如’#‘表示出来,比较浪费空间

现在主要介绍二叉树的链式存储结构的操作

BTNode *Create_BTree(BTNode *bt)
{//建立一个二叉树
    ElemType e;
    cin>>e;
    if(e == '#')return NULL;
    else
    {
        bt = new BTNode;
        bt->data = e;
        Create_BTree(bt->lchild);
        Create_BTree(bt->rchild);
    }
}
/*********************************************
如果你想创建的树的逻辑结构如下A(B(C,D),E(F,G))
那么你需要输入ABC##D##EF##G##
**********************************************/

void Destroy_BTree(BTNode *bt)
{//销毁一棵二叉树
    if(bt == NULL)
        return;
    else
    {
        Destroy_BTree(bt->lchild);
        Destroy_BTree(bt->rchild);
    }
}

void Disp_BTree(BTNode *bt)
{//逻辑上输出一棵二叉树
    if(bt != NULL)
    {
        cout<<bt->data;//输出根节点
        if(bt->lchild != NULL || bt->rchild != NULL)
        {
            cout<<"(";
            DispBTree(bt->lchild);//输出左子树
            if(bt->rchild != NULL)cout<<",";
            DispBTree(bt->rchild);//输出右子树
            cout<<")";
        }
    }
}

/*****************************************************
二叉树的遍历分为三种,前序遍历,中序遍历,后续遍历
下列程序均使用递归来实现二叉树的遍历
******************************************************/
void visit(BTNode *bt)
{//输出二叉树的一个结点
    cout<<bt->data<<" ";
}

void Preorder(BTNode *bt)
{//前序遍历
    if(bt != NULL)
    {
        visit(bt);
        Preorder(bt->lchild);
        Preorder(bt->rchild);
    }
}

void Inorder(BTNode *bt)
{//中序遍历
    if(bt != NULL)
    {
        Inorder(bt->lchild);
        visit(bt);
        Inorder(bt->rchild);
    }
}

void Postorder(BTNode *bt)
{//后续遍历
    if(bt != NULL)
    {
        Postorder(bt->lchild);
        Postorder(bt->rchild);
        visist(bt);
    }
}

/**********************************************
二叉树的层次遍历,也就是从上至下从左至右依次输出
***********************************************/
void Levelorder(BTNode *bt)
{//层次遍历
    BTNode *p;
    BTNode *qu[MAXSIZE];//定义一个队列,因为要用到其FIFO的特性
    int front , rear;
    front = rear = -1;
    rear++;
    qu[rear] = bt;
    while(front != rear)
    {
        front = (front + 1) % MAXSIZE;
        p = qu[front];
        cout << p->data;
        //依次将一层的左子树右子树输入到队列之中
        if(bt->lchild != NULL)
        {
            front = (front + 1) % MAXSIZE;
            qu[front] = bt->lchild;
        }
        if(bt->rchild != NULL)
        {
            front = (front + 1) % MAXSIZE;
            qu[front] = rt->lchild;
        }
    }
}

BTNode *Find_Node(BTNode *bt,ElemType x)
{//查找二叉树中值为x的结点,存在则返回结点,不存在则返回0
    BTNode *p;
    if(bt == NULL)return 0;
    else if(bt->data == x)return bt;
    else
    {
        p=Find_Node(bt->lchild,x);
        if(p != NULL)return p;
        else return Find_Node(bt->rchild,x);
    }
}       

BTNode *Find_lchild(BTNode *bt)
{//查找bt结点的左孩子
    return bt->lchild;
}

BTNode *Find_rchild(BTNode *bt)
{//查找bt结点的右孩子
    return bt->rchild;
}

int Depth_BTree(BTNode *bt)
{//求二叉树的高度
    int ldepth,rdepth;//求左子树的高度和右子树的高度
    if(bt == NULL)return 0;
    else
    {
        ldepth = Depth_BTree(bt->lchild);
        rdepth = Depth_BTree(bt->rchild);
        return (ldepth>rdepth?ldepth:rdepth)+1;
    }
}

int Count_BT_Node(BTNode *bt)
{//求结点的个数
    if(bt == NULL)return 0;
    else return Count_BT_Node(bt>lchild)
                +Count_BT_Node(bt->rchild)+1;
}

int Count_BT_Leaf(BTNode *bt)
{//求叶子结点的个数
    int num1,num2;
    if(bt == NULL) return 0;
    else if (bt->lchild == NULL && bt->rchild == NULL)
        return 1;
    else
    {
        num1=Count_BT_Leaf(bt->lchild);     
        num2=Count_BT_Leaf(bt->rchild);
        return num1+num2;
    }
}

void Copy_BT(BTNode *b,BTNode *t)
{//复制b到t
    if(b == NULL)t==NULL;
    else
    {
        t=new BTNode;
        t->data = b->data;
        Copy_BT(b->lchild,t->lchild);
        Copy_BT(b->rchild,t->rchild);
    }
}

void Swap_BT(BTNode *b,BTNode *t)
{//交换b的左右子树,要求不破坏原来的结构
    if(b == NULL)t == NULL;
    else
    {
        t=new BTNode;
        t->data = b->data;
        Swap_BT(b->lchild,t->rchild);
        Swap_BT(b->rchild,t->lchild);
    }
}

int l = 0;
int Find_Node_Level(BTNode *bt,ElemType x,int h)
{//查找结点所在的层次
    if(bt == NULL)return 0;
    h++;
    if(bt->data == x)return h;
    else
    {
        l=Find_Node_Level(bt->lchild);
        if(l = 0)
            return Find_Node_Level(bt->rchild);
        return l;
    }
}

void All_Path1(BTNode *bt)//非递归算法
{//输出从根结点到叶子结点的所有路径
    if(bt == NULL)return;//bt为空树,直接返回
    else
    {
        struct node
        {
            BTNode *node;
            int parent;
        }qu[MAXSIZE];//创建一个队列,队列元素是树的结点和定义的父母元素,方便返回
        int front,rear,p;
        BTNode *q;
        front = rear = -1;  
        rear++;
        qu[rear].node = bt;//树根存储在队列的右端
        qu[rear].parent = -1;//到达树根的标记,根节点没有双亲节点
        whilw(front != rear)//循环开始
        {
            front++;
            q = qu[front].node;//q指向队列的左端
            if(q->lchild == NULL && q->rchild == NULL)
            {
                p = front;
                while(qu[p].parent != -1)
                {
                    cout<<qu[p].node->data<<" ";
                    p=qu[p].parent;
                }
                cout<<qu[p].node->data<<" ";
                cout<<endl;
            }
            if(q->lchild != NULL)
            {
                rear++;
                qu[rear].node = q->lchild;
                qu[rear].parent = front;
            }
            if(q->rchild != NULL)
            {
                rear++;
                qu[rear].node = q->rchild;
                qu[rear].parent = front;
            }
        }
    }
void All_Path2(BTNode *bt,vector<ElemType> path)//递归算法
{
    if(bt == NULL)return;
    else
    {
        path.push_back(bt->data);
        if(bt->lchild == NULL && bt->rchild == NULL)
        {
            for(vector<ElemType>::iterator iter=path.begin();
            itre!=path.end();
            iter+++)
                cout<<*iter<<" ";
            cout<<endl;
            return;
        }
        else
        {
            All_Path2(bt->lchild,path);
            All_Path2(bt->rchild,path);
        }
    }
}

/****************************************************
可以有先序序列和中序序列或者是后序序列和中序序列唯一的确定一颗二叉树
通过前序序列和中序序列构造一颗二叉树
preorder:A B D E C F G
inorder :D B E A F G C
preorder的第一个A是树的根,在inorder里边找到
**A** B D E C F G
D B E **A** F C G
左子树的preorder为**B** D E
      inorder 为D **B** E
右子树的preorder为**C** F G
      inorder 为F **C** G
则左子树的根为B,依次类推
右子树同上
通过前序序列和中序序列构造一颗二叉树
preorder:A B D E C F G
inorder :D B E A F G C
preorder的第一个A是树的根,在inorder里边找到
**A** B D E C F G
D B E **A** F C G
左子树的preorder为**B** D E
      inorder 为D **B** E
右子树的preorder为**C** F G
      inorder 为F **C** G
则左子树的根为B,依次类推
右子树同上

通过后序序列和中序序列构造一颗二叉树
postorder:D E B F G C A
inorder :D B E A F G C
postorder的最后一个A是树的根,在inorder里边找到
D E B F G C **A**
D B E **A** F C G
左子树的postorder为D E **B**
      inorder 为D **B** E
右子树的postorder为F G **C**
      inorder 为F **C** G
则左子树的根为B,依次类推
右子树同上
*****************************************/      
//代码如下
BTNode *Create_BT1(char *pre,char *in,int n)
{//通过前序序列和中序序列建立一棵二叉树
    BTNode *bt;
    char *p;
    int k;
    if(n<=0)bt=NULL;
    else
    {
        bt->data = *pre;
        while(p=in;p<in+n;p++)
            if(*pre=*p)
                break;
        k=p-in;
        bt->lchid=Create_BT1(pre+1,in,k);
        bt->rchild=Create_BT2(pre+k+1,p+1,n-k-1);
    }
    return bt;
}

BTNode *Create_BT2(char *post,char *in,int n)
{//通过后序序列和中序序列创建一颗二叉树
    BTNode *bt;
    char r,*p;
    int k;
    if(n<=0)bt=NULL;
    else
    {
        r=*(post+n-1);
        bt = new BTNode*;
        bt->data = r;
        for(p=in;p<in+n;p++)
            if(*p==r)
                break;
        bt->lchid=Create_BT2(post,in,k);
        bt->rchild=Create_BT2(post+k,p+1,n-k-1);
    }
}

BTNode *trans(SqBTree a, int i)
{//将顺序存储结构转化为链式存储结构
    BTNode *p;
    if (i > MAXSIZE) return NULL;
    if (a[i].data == '#')   return NULL;
    else
    {
        p = new BTNode;
        p->data = a[i].data;
        p->lchild = trans(a, 2 * i);
        p->rchild = trans(a, 2 * i + 1);
    }
    return p;
}

void trans2(BTNode *bt, SqBTree a, int i)
{//将链式存储结构转化为顺序存储结构
    if (bt != NULL)
    {
        a[i].data = bt->data;
        trans2(bt->lchild, a, 2 * i);
        trans2(bt->rchild, a, 2 * i + 1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值