树和二叉树

来源:互联网 发布:万网怎么注册域名 编辑:程序博客网 时间:2024/05/16 02:00

树是n个结点的有限集。二叉树是一种树形结构,它的特点是每个结点至多只有两棵子树,并且子树有左右之分,其次序不能任意颠倒。深度为k的二叉树至多有(2^k)-1个结点,有(2^k)-1个结点的称为满二叉树。深度为k的有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树编号从1到n的结点一一对应时,称为完全二叉树。

二叉树的存储结构有两种,顺序存储结构以及链式存储结构。顺序存储结构即采用一组地址连续的空间来存放数据,如利用数组。顺序存储方式仅适用于于完全二叉树,对于一般二叉树来说空间利用率低。链式存储结构的每一个结点至少包含3个域:数据域、左指针域、右指针域,有时为了便于寻找根结点,还可在结点结构中增加一个指向其根结点的指针域。这种结构分别称为二叉链表和三叉链表。实现为:

typedef struct bitnode    {        int data;        struct bitnode *lchild,*rchild;    }bitnode,*bitree;

对二叉树的遍历有先序遍历、中序遍历、后序遍历三种

#include<iostream>using namespace std;typedef struct bitnode    {        int data;        struct bitnode *lchild,*rchild;    }bitnode,*bitree;void traveltree(bitree T);void visit(bitree T);int main(){    /*先初始化二叉树*/    bitnode bitnode[7];    int i;    for(i=0;i<7;i++)    {        bitnode[i].data =i;    }    for(i=0;i<3;i++)    {        bitnode[i].lchild =&bitnode[2*i+1];        bitnode[i].rchild =&bitnode[2*i+2];    }    for(i=3;i<7;i++)    {        bitnode[i].lchild=NULL;        bitnode[i].rchild=NULL;    }    traveltree(bitnode);    return 0;}void traveltree(bitree T){    /*先序遍历*/    if(T!=NULL)    {        visit(T); /*对各点的操作*/        traveltree(T->lchild );        traveltree(T->rchild );    }    else    {    }}/*void traveltree(bitree T)//中序遍历{    if(T!=NULL)    {        traveltree(T->lchild );        visit(T);        traveltree(T->rchild );    }    else    {    }}void traveltree(bitree T)//后序遍历{    if(T!=NULL)    {        traveltree(T->lchild );        traveltree(T->rchild );        visit(T);    }    else    {    }}*/void visit(bitree T){    (T->data) ++;}

对于先序遍历,每个结点都会比它的左子树上的所有结点和右子树上的所有结点(如果存在)先被访问,而左子树上的结点总会比右子树上的结点先被访问;
对于中序遍历,每个结点都会在它的左子树上的所有结点被访问后才访问,但比它的右子树上的所有结点先被访问;
对于后序遍历,每个结点都会在它的左子树上的所有结点和右子树上的所有结点(如果存在)被访问后才访问,而左子树上的结点总会比右子树上的结点先被访问。

如对于下图:
这里写图片描述
先序遍历:A B C D E G F
中序遍历:C B E G D F A
后序遍历:C G E F D B A
(思考过程:如对于中序遍历,BCDEFG都在A的左子树上,所以它们都比A先被访问;C位于B的左子树上,所有C比B先被访问,DEFG位于B的右子树上,所有B比DEFG先被访问;EG位于D的左子树上,所以EG比D先被访问,F位于D右子树上,所有D比F先被访问;G位于E的右子树上,所以E比G先被访问)


树的存储结构有三种:双亲表示法、孩子表示法、孩子兄弟表示法
双亲表示法利用了每个结点(除根结点)只有唯一一个双亲的特点,每个结点的结构中除了该结点的数据外,还有双亲的位置信息。

#define max_tree_size 100typedef struct ptnode{    /*结点结构*/    int data;    int parent;   /*双亲位置域,即数组下标值*/}ptnode;typedef struct{    /*树结构*/    ptnode nodes[max_tree_size];    int r,n;   /*根的位置,结点数*/}ptree;

孩子表示法是每个结点结构中除了该结点的数据信息外,还包含了该结点的孩子结点。但由于每个结点的度不同,所以会造成空间的浪费。另一种方法是将该结点的孩子结点排列起来,看成是一个线性表,该表示方法的实现为:

#define max_tree_size 100typedef struct ctnode{    int child;    struct ctnode *next;   }*childptr;typedef struct{    int data;    childptr firstchild;}ctbox;typedef struct{    /*树结构*/    ctbox nodes[max_tree_size];    int r,n;   /*根的位置,结点数*/}ctree;

孩子兄弟表示法的每个结点结构中除了数据元素外,还包含了该结点的第一个孩子结点和下一个兄弟结点。

typedef struct csnode{    int data;    struct csnode *firstchild,*nextsibling;}csnode,*cstree;
0 0
原创粉丝点击