Study Notes - Tree

table of Contents

 

The basic operation of the tree

Preamble, in order, a subsequent traversal (recursive)

Preorder traversal (non-recursive, by means of the stack)

In order traversal (non-recursive, by means of the stack) 

Postorder (non-recursive, by means of the stack) 

Traverse the level (through queue)

Height function returns a binary tree height

Size function returns the number of nodes in a binary tree


The basic operation of the tree

Binary tree node structure definition

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

Create a new tree node

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

Binary tree structure definition

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

Creating an empty binary tree

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

Root BinaryEmpty (T) T is detected root pointer is empty

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

Root (T) to return the root node numeral

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

MakeTree (x, T, L, R) to x is a root element, respectively, L and R for the left and right subtree construct a new binary tree T.

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

Function BreakTree (T, L, R) execute a function MakeTree inverse operation of the binary tree split root element T element, 3 L three parts left subtree and right subtree R and the like.

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

Preamble, in order, a subsequent traversal (recursive)

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 (non-recursive, by means of the stack)

//前序遍历
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);
        }
    }
}

 

In order traversal (non-recursive, by means of the stack) 

//中序遍历
/*若栈顶结点左孩子存在,则左孩子入栈,若左孩子不存在,则输出并弹出栈顶,然后检查其右孩子是否存在,若存在则右孩子入栈*/
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,继续弹出栈顶元素
        }
    }
}

Postorder (non-recursive, by means of the stack) 

//后序遍历
//定义枚举类型: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 the level (through queue)

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);
    }
}

 

Height function returns a binary tree height

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

Size function returns the number of nodes in a binary tree

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

 

Published 35 original articles · won praise 2 · Views 1389

Guess you like

Origin blog.csdn.net/weixin_41001497/article/details/101076141