zoukankan      html  css  js  c++  java
  • 树&二叉树

    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
    ",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;
    } 

        

        

  • 相关阅读:
    ThinkPHP中自定义常量
    【转】在Asp.net中弹出对话框,然后跳转到其他页面问题
    【转】SVN版本控制器的安装和配置
    【原】用上传控件进行文件上传时,页面程序代码都不执行,显示“页面信息无法显示”
    【转】net Web Service 方法重载
    【转】SQL里的EXISTS与in、not exists与not in
    【转】利用wsdl.exe生成webservice代理类
    【转】获取图片大小
    【转】用了AJAX后,不能用javascript弹出对话框
    【转】net Web Service 方法重载
  • 原文地址:https://www.cnblogs.com/foodie-nils/p/13972844.html
Copyright © 2011-2022 走看看