Notas de Estudio - Tree

directorio

 

El funcionamiento básico del árbol

Preámbulo, en orden, un recorrido posterior (recursiva)

Preorder traversal (no recursivo, por medio de la pila)

En traversal orden (no recursivo, por medio de la pila) 

Postorden (no recursivo, por medio de la pila) 

Traverse el nivel (a través de la cola)

función de altura devuelve una altura de árbol binario

Función de tamaño devuelve el número de nodos en un árbol binario


El funcionamiento básico del árbol

árbol binario nodo de estructura de definición

typedef struct btnode *btlink //定义一个指向数据类型为btnode的指针
typedef struct btnode
{
    TreeItem element;
    btlink *lchild;
    btlink *rchild;
}Btnode;

Crear un nuevo nodo del árbol

btlink NewBNode()    //返回值是一个指针,即新结点的地址值
{
    btlink p;
    p=malloc(sizeof(Btnode));
    if(p)    //申请地址成功
        return p;
    else
        Error("Exhausted memory.");
}

árbol binario estructura de definición

typedef struct binarytree *BinaryTree;
typedef struct binarytree
{
    btlink root;    //root是指向树根的指针,一个二叉树只要知道其树根便可唯一确定
}BTree;

Creación de un árbol binario vacío

BinaryTree BinaryInit()
{
    BinaryTree T=malloc(sizeof(*T));
    T->root=0;    //初始化指针,未指向任何空间
    return T;
}

BinaryEmpty raíz (T) T se detectó puntero raíz está vacía

int BinaryEmpty(BinaryTree T)    //这里的T是指针,指向一个二叉树的根结点
{
    return(T->root==0)
}

Root (T) para devolver el numeral nodo raíz

TreeItem Root(BinaryTree T)
{
    if(BinaryEmpty(T))
    {
        Error("Tree is empty.");
    }
    else return T->root->element;
}

MakeTree (x, T, L, R) a x es un elemento raíz, respectivamente, L y R para el constructo subárbol izquierdo y derecho un nuevo T. árbol binario

void MakeTree(TreeItem x,BinaryTree T,BinaryTree L,BinaryTree,R)
{
    T->root=NewBNode();
    T->root->data=x;
    T->root->lchild=L->root;
    T->root->rchild=R->root;
    L->root=R->root=0;
}

Función BreakTree (T, L, R) ejecutar una operación de la función MakeTree inversa de la fracción de árbol de elementos elemento raíz T binario, 3 L de tres partes izquierda y derecha de subárbol subárbol R y similares.

TreeItem BreakTree(BinaryTree T,BinaryTree L,BinaryTree R)
{
    TreeItem x;
    if(!T->root) Error("Tree is Empty!");
    x=T->root->element;
    L->root=T->root->lchild;
    R->root=T->root->rchild;
    T->root=0;
    return x;
}

Preámbulo, en orden, un recorrido posterior (recursiva)

void PreOrder(void (*visit)(btlink u),btlink t)
{
    /*前序遍历*/
    if(t)
    {
        (*visit)(t);
        PreOrder(visit,t->lchild);
        PreOrder(visit,t->rchild);
    }
}

void InOrder(void (*visit)(btlink u),btlink t)
{
    /*中序遍历*/
    if(t)
    {
        PreOrder(visit,t->lchild);
        (*visit)(t);
        PreOrder(visit,t->rchild);
    }
}

void PostOrder(void (*visit)(btlink u),btlink t)
{
    /*后序遍历*/
    if(t)
    {
        PreOrder(visit,t->lchild);
        PreOrder(visit,t->rchild);
        (*visit)(t);
    }
}

Preorder traversal (no recursivo, por medio de la pila)

//前序遍历
void PreOrderWithoutRecursion1(BTNode* root)
{
    if (root == NULL)
        return;
    BTNode* p = root;
    stack<BTNode*> s;
    while (!s.empty() || p)
    {
        //边遍历边打印,并存入栈中,以后需要借助这些根节点(不要怀疑这种说法哦)进入右子树
        while (p)
        {
            cout << setw(4) << p->data;
            s.push(p);
            p = p->lchild;
        }
        //当p为空时,说明根和左子树都遍历完了,该进入右子树了
        if (!s.empty())
        {
            p = s.top();
            s.pop();
            p = p->rchild;
        }
    }
    cout << endl;
}
void preorderNonrecursion(BTNode *bt)
{
    if(bt!=NULL)
    {
        stack<BTNode*> s;
        BTNode *p;
        s.push(bt);
        while(!IsEmpty(s))
        {
            p=s.pop();    //每有一个结点进栈,就执行一次弹出栈顶结点并压入其右左孩子结点的操作
            visit(p);
            if(p->rchild!=NULL)    //记住是右子树先入栈,左子树后入栈,才能保证左子树先于右子树被访问
                s.push(p->rchild);
            if(p->lchild!=NULL)
                s.push(p->lchild);
        }
    }
}

 

En traversal orden (no recursivo, por medio de la pila) 

//中序遍历
/*若栈顶结点左孩子存在,则左孩子入栈,若左孩子不存在,则输出并弹出栈顶,然后检查其右孩子是否存在,若存在则右孩子入栈*/
void InOrderWithoutRecursion1(BTNode* root)
{
    //空树
    if (root == NULL)
        return;
    //树非空
    BTNode* p = root;
    stack<BTNode*> s;
    while (!s.empty() || p)
    {
        //一直遍历到左子树最下边,边遍历边保存根节点到栈中
        while (p)
        {
            s.push(p);
            p = p->lchild;
        }
        //当p为空时,说明已经到达左子树最下边,这时需要出栈了
        if (!s.empty())
        {
            p = s.top();
            s.pop();
            cout << setw(4) << p->data;
            //进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
            p = p->rchild;    //如果有右子树,就走while,把右子树压入栈,若无右子树,就走if,继续弹出栈顶元素
        }
    }
}

Postorden (no recursivo, por medio de la pila) 

//后序遍历
//定义枚举类型:Tag
enum Tag{left,right};
//自定义新的类型,把二叉树节点和标记封装在一起
typedef struct
{
    BTNode* node;
    Tag tag;
}TagNode;    
//后序遍历  
void PostOrderWithoutRecursion2(BTNode* root)
{
    if (root == NULL)
        return;
    stack<TagNode> s;
    TagNode tagnode;
    BTNode* p = root;
    while (!s.empty() || p)
    {
        while (p)
        {
            tagnode.node = p;
            //该节点的左子树被访问过
            tagnode.tag = Tag::left;
            s.push(tagnode);
            p = p->lchild;
        }
        tagnode = s.top();
        s.pop();
        //左子树被访问过,则还需进入右子树
        if (tagnode.tag == Tag::left)
        {
            //置换标记
            tagnode.tag = Tag::right;
            //再次入栈
            s.push(tagnode);
            p = tagnode.node;
            //进入右子树
            p = p->rchild;
        }
        else//右子树已被访问过,则可访问当前节点
        {
            cout << setw(4) << (tagnode.node)->data;
            //置空,再次出栈(这一步是理解的难点),p=NULL下一层循环直接执行while(p){}后面的语句,即继续弹出栈顶
            p = NULL;
        }
    }
    cout << endl;
}

 

/*依据:逆后序遍历=先序遍历中左右子树访问顺序对调*/
void postordernonrecursion(BTNode *bt)
{
    stack <BTNode*> s1,s2;
    BTNode *p;
    s1.push(bt);
    while(!IsEmpty(s1))
    {
        p=s1.pop();
        s2.push(p);    //访问到的结点压入s2
        if(p->lchild!=NULL)
            s1.push(p->lchild);
        if(p->rchild!=NULL)
            s2.push(p->rchild);    //先压入左子树再压入右子树,保证弹栈时先弹出右子树
    }
    while(!IsEmpty(s2))
    {
        p=s2.pop();
        visit(p);
    }
}

Traverse el nivel (a través de la cola)

void LevelOrder(void (*visit)(btlink u),btlink t)
{
    Queue q=QueueInit();
    EnQueue(t,q);
    while(!QueueEmpty(q))
    {
        (*visit)(t=DeQueue(q));
        if(t->lchild) EnQueue(t->lchild,q);
        if(t->rchild) EnQueue(t->rchild,q);
    }
}
void Level(BTNode *bt)
{
    InitQueue(Q);
    BTNode *p;
    EnQueue(Q,bt);
    while(!IsEmpty(Q))
    {
        DeQueue(Q,p);
        visit(p);
        if(p->lchild!=NULL)
            EnQueue(Q,p->lchild);
        if(p->rchild!=NULL)
            EnQueue(Q,p->rchild);
    }
}

 

función de altura devuelve una altura de árbol binario

int Height(btlink t)
{
    int hl,hr;
    if(!t) return -1;
    hl=Height(t->lchild);
    hr=Height(t->rchild);
    return hl>hr?++hl:++hr;//取左右子树中高度较大者的高度加上自身根结点的高度
}

Función de tamaño devuelve el número de nodos en un árbol binario

int Size(btlink t)
{
    if(!t) return 0;
    int lsize=Size(t->lchild);
    int rsize=Size(t->rchild);
    return lsize+rsize+1;//左子树结点数+右子树结点数+自身根结点数1
}

 

Publicado 35 artículos originales · ganado elogios 2 · Vistas 1389

Supongo que te gusta

Origin blog.csdn.net/weixin_41001497/article/details/101076141
Recomendado
Clasificación