zoukankan      html  css  js  c++  java
  • 树的基本操作

    一、关于树:
     
     数的定义是递归的:
     定义树是满足以下条件的,包含至少一个结点的有限集合:
     
    (1)树中有一个特别指定的结点,称为根,或树根。
    (2)其它结点划分成n>=0个不相交的集合T1…Tn ,每个集合又还是一棵树,但称为根的子树。
         树的主要操作包括:求树的深度、求给定节点的子节点、兄弟节点、遍历树、插入子树、删除子树等等。
         因为树的定义本身就是递归的,所以在实际的程序中,很多操作也是通过递归来完成的。树是如何表示的
         呢?有一种常用的表示方法,成为孩子、兄弟表示法,对于每个节点,通过孩子指针指向自己的子节点,
         通过兄弟指针指向自己右边的兄弟。
     
    二、树的存储方法:
     
    双亲表示法(顺序存储)
    孩子表示法(顺序存储与链式存储结合)
    孩子兄弟表示法/二叉树表示法/二叉链表表示法(顺序存储与链式存储结合)(左链域为该节点的第一个孩子,右链域为该节点的下一个兄弟)
     
    三、基本操作:
     
    //节点
    typedef struct CSNode{
          char data;
          struct SCNode *firstchild,*nextsibling;
    }TNode,*Tree;
     
     
    构造树与删除树,插入子树与删除子树
     
    1.构造树
     
    Tree InitTree(){
      Tree T=NULL;
      int ch;
      ch=getchar();
      if(ch!='#'){
           T=(Tree)malloc(sizeof(TNode));
           T->firstchild=NULL;
           T->nextsibling=NULL;
           T->data=ch;
      }
      return T;
    }
     
     
     
    2.插入子树
     
    Tree pos=NULL;     //标记子树的父节点的位置
    bool insertSubTree(Tree T,ElemType e,Tree Tadd)
    {
        locateElem(T,e);     //查找到其父节点位置
        if(pos!= NULL)
        {
            Tadd->nextSibling=pos->firstChild;  //将新子树根节点作为该节点的最左孩子
            pos->firstChild=Tadd;
            return true;
        }
        else
            return false;
    }
     
    3.删除树(调用删除函数逐个删除节点)
     
    void deleteTree(Tree T){
        if(!T)
            return OK;
        else{
            deleteTree(T->firstchild);
            deleteTree(T->nextsibling);
            free(T);
            T=NULL;
        }
    }
     
    4.删除子树
     
    Tree pos=NULL;//标记其父节点的位置
    bool deleteSubTree(Tree T,ElemType e)
    {
        locateElem(T,e);
     
        //先判断pos是否有孩子节点
        if(pos->firstChild!=NULL)
        {
            deleteTree(pos->firstChild);   //调用删除树函数,删除以该节点最左孩子为根节点的子树
            return true;
        }
        else
            return false;
    }
     
    ----------------------------------------------------------------------------------------
     
     遍历树
    //先序遍历
    void TraverseTree(Tree T){
        if(T){
            visit(T->data);
            TreaverseTree(T->firstchild);
            TreaverseTree(T->nextsibling);
        }
        return 0;
    }
    //或者
    void TraverseTree(Tree T){
        Tree p;
        if(T){
            visit(T->data);
            p=T->firstchild;
            while(!p){
                TreaverseTree(p);
                p=p->nextsiling;
            }
        }
        return 0;
    }
    ------------------------------------------------------------------------------------------
    查找某个节点x,查找左孩子,右兄弟
     
    Tree p;   //用全局变量标记查找到的节点
    Tree searchnode(Tree  &T,char ch){
        p=T;
        if(T){
            if(p->data==ch)
                return p;
            else{
                p=T->firstchild;
                while(p){
                searchnode(p->firstchild,ch);
                p=p->nextsibling;
                }
            }
       return Null;
    }
     
    1.查找某个节点的左孩子
     
    Tree findChild(Tree T,ElemType e)
    {
        searchnode(T,e);
        //如果没有找到或者该节点是叶子节点,返回空
        if( p==NULL&&NULL==p->firstChild)
            return NULL;
        else
            return p->firstChild;
    }
     
    2.查找某个节点的右兄弟
     
    Tree findSibling(Tree T,ElemType e)
    {
        searchnode(T,e);
        //如果没有找到或者该节点没有右兄弟,返回空
        if(p==NULL&&p->nextSibling==NULL)
            return NULL;
        else
            return p->nextSibling;
    }
     
    ------------------------------------------------------------------------------------------
    求树的高度
     
    void TreeDepth(Tree T){
        int height=0,hmax=0;
        if(T){
          Tree p=T->firstchild;
          while(p){
             height=TreeDrpth(p);
             p=p->nextsibling;
             if(hmax
                hmax=height;
          }
       }
       return hmax+1;
    }
    --------------------------------------------------------------------------------------
     
     
     总结:对于树的核心操作,毫无疑问是如何递归的遍历一棵树。我们的作法是这样的:
    对于一个节点,先访问它的数据域,然后通过孩子指针来访问它的孩子,一直到
    沿着这条分支的叶子节点,此时,访问这个节点的兄弟,直到所有的兄弟都访问
    过了,然后回退到上一节点,访问它的兄弟,依次类推。
  • 相关阅读:
    3139:[HNOI2013]比赛
    3143: [Hnoi2013]游走
    目前游戏行业内部主要几款游戏引擎的技术对比
    6.使用AngularJS模板来创建视图
    css选择器(E[att^=”val”]序号选择器)
    5.把作用域实现为数据模型
    4.了解AngularJS模块和依赖注入
    3.创建基本的AngularJS应用
    2.AngularJS MVC
    1.AngularJS初探
  • 原文地址:https://www.cnblogs.com/yujon/p/5467592.html
Copyright © 2011-2022 走看看