树&二叉树

1.树

  树的定义:树是n(n>=0)个结点的有限集合,当n=0时称为空树。对于任意一颗非空树应该满足以下条件:

    a.有且仅有一个根节点

    b.当n>1时,其余结点可以分为m个互不相交的有限集合T1,T2...Tm,其中每个集合又是一棵树,并且是根的子树

  基本术语:

    树中一个结点的孩子的个数称为树的度,其中拥有最大度的结点的度称为树的度。

    度大于0的结点称为分支结点/非终端结点,度为0的结点称为叶子结点。

    层次:结点的层次从树根开始定义,根节点为第一层。

    深度:从根节点开始自顶向下累加

    高度:从最下面的结点自底向上累加

    有序树和无序树:结点的各个子树顺序有所谓(不能互换)则称为有序树,无所谓(可以随意互换)则称为无序树

    路径和路径长度:从A结点到B结点所经过的所有结点序列,路径长度是这条路径上的结点个数

    森林:m个树一起(m>=0)构成森林,如果给这m个树加一个共同的根节点,那么这个森林就变成了一棵树

  树的性质:

    结点数等于所有结点的度数加1

    度为m的树第i层最多有mi-1个结点。

    高度为h的m叉树最多有(mh-1)/(m-1)个结点

  树的存储结构:

    双亲表示法:用一组连续的空间来存储每个结点,每个结点中增加一个数据域作为伪指针,指向该结点的父节点对应的数组下标

//双亲表示法,根节点下标为0,其伪指针域为-1 
typedef struct{
    ElementType data;
    int parent;
}node;
typedef struct{
    node N[MAX_SIZE];
    int n;
}Tree;

 

    孩子表示法:链式存储结构,因为每个结点的结构需要一致,但是每个结点拥有的孩子数量又往往不同,因此父节点中只设一个指向孩子结点的指针,在孩子 结点中也加设一个指针域,指向它的下一个兄弟结点。

//孩子表示法
typedef struct child{
    int n;
    child* next;    
}*nextChild;
typedef struct{
    ElementType data;
    child* firstChild;
}node;
typedef struct{
    node N[MAX_SIZE];
    int n,r;            //结点数量和根节点    
}Tree;

 

    孩子兄弟表示法:孩子表示法需要区别父节点和孩子结点,而孩子兄弟表示法中所有结点的结构都是一样的

typedef struct node{
    ElementType data;
    struct node* firstChild;
    struct node* nextSibling;    
}node,*Tree;

 

  树、森林、二叉树的转换:树转换为二叉树就是将树用孩子兄弟表示法来存储各个结点,得到的链式结构对应的就是相应的二叉树,森林转换为二叉树的时候,先将森林中的每棵树转化为二叉树,再将得到的二叉树的根节点看作是同一层次的兄弟,用第一个根节点的右指针域指向第二个根节点,第二个根节点指向第三个根节点,依次类推。

 

  树的遍历:

    先序遍历:先访问父节点,再访问孩子结点

    后序遍历:先访问孩子结点,再访问父节点  (相当于把树转化为二叉树链式存储时候的中序遍历)

  森林的遍历:

    先序遍历森林:

      访问森林中第一棵树的根节点

      先序遍历第一棵树中根节点的子树森林

      先序遍历除去第一棵树之后剩余的树构成的森林

    中序遍历森林:(注意此遍历是指将森林用二叉树的存储方式链式存储(兄弟孩子表示法)时候的遍历规则,它相当于对每一棵树进行后续遍历)

      中序遍历森立中第一棵树的根节点的子树森林

      访问第一棵树的根节点

      中序遍历除去第一棵树之后剩余的树构成的森林

2.二叉树

  二叉树的定义:度数为2的有序树 

  几个特殊的二叉树:

    满二叉树:每一层都含有最大数量的结点的二叉树

    完全二叉树:除了最下面一层外,每一层都含有最大数量的结点的二叉树,且最下面一层的结点从左到右排列没有空缺的位置

  二叉树的存储结构:

    顺序存储结构:通常只用顺序存储结构保存完全二叉树,这么做的好处是可以根据数组的index来确定一个结点的孩子

    链式存储结构:

/**@数据结构:树->二叉树 
 **@作者:9761滴  
 **@存储结构:链表 
 **/
 
//本文件中实现了二叉树的
    /*1.前 中 后序遍历以及层序遍历 的递归算法和非递归算法 
        **PreOrder()
        **InOrder()
        **PostOrder() 
        **LevelOrder()
    */ 
//等操作 
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
typedef int ElementType;
//二叉树结点的结构体 
typedef struct BNode{
    ElementType data;
    BNode *lchild,*rchild;
}BNode,*BTree;
//线索二叉树结点的结构体

void visit(BTree T){
    printf("%d\n",T->data);
}
//前序遍历,递归实现 
void PreOrder(BTree T){
    if(T!=NULL){
        visit(T);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    } 
}

//前序遍历,非递归实现 
void PreOrder2(BTree T){
    stack<BNode*> S;
    BTree P=T;
    while(P!=NULL||!S.empty()){
        if(P){
            visit(P);
            S.push(P);
            P=P->lchild;
        }
        else{
            P=S.top();
            S.pop();
            P=P->rchild;
        }
    }
}
//中序遍历,递归实现
void InOrder(BTree T){
    if(T!=NULL){
        InOrder(T->lchild);
        visit(T);
        InOrder(T->rchild);    
    }
} 
//中序遍历,非递归实现 
void InOrder2(BTree T){
    stack<BNode*> S;
    BTree P=T;
    while(!S.empty()||P!=NULL){
        if(P!=NULL){
            S.push(P);
            P=P->lchild;
        }
        else{
            P=S.top();
            S.pop();
            visit(P);
            P=P->rchild;
        }
    }
}
//后序遍历,递归实现 
void  PostOrder(BTree T){
    if(T!=NULL){
        PostOrder(T->lchild);
        PostOrder(T->rchild);
        visit(T);
    }
}
//后序遍历,非递归实现
void  PostOrder2(BTree T){
    stack<BNode*> S;
    BTree P=T;
    BTree R=NULL;
    while(P!=NULL||!S.empty()){
        if(P!=NULL){
            S.push(P);
            P=P->lchild;
        }
        else{
            P=S.top();
            if(P->rchild==NULL){
                visit(P);
                S.pop();
                R=P;
                P=NULL;
            }
            else if(R!=P->rchild){
                P=P->rchild;
                S.push(P);
                P=P->lchild;
            }

        }
    }
}
//层序遍历 
void LevelOrder(BTree T){
    queue<BNode*> Q;
    Q.push(T);
    BTree P;
    while(!Q.empty()){
        P=Q.front();
        Q.pop();
        visit(P);
        if(P->lchild){
            Q.push(P->lchild);
        }
        if(P->rchild){
            Q.push(P->rchild);
        }
    }
}
int main(){
    return 0;
} 

 

    

    

posted @ 2020-11-14 12:16  9761滴  阅读(92)  评论(0编辑  收藏  举报