二叉树 基础操作

2018-03-23  本文已影响0人  开发者zhang

二叉树的使用

typedef struct BTNode{
    int data;
    struct BTNode *lChild;\\左子树
    struct BTNode *rChild;\\右子树
}BiTNode;
int CreateBiTree(BiTNode **T)
{
    int ch;
    scanf("%d",&ch);
    if (ch == -1)
    {
        *T = NULL;
        return 0;
    }
    else
    {
        *T = (BiTNode *)malloc(sizeof(BiTNode));
        if (T == NULL)
        {
            printf("failed\n");
            return 0;
        }
        else
        {
            (*T)->data = ch;
            printf("输入%d的左子节点:",ch);
            CreateBiTree(&((*T)->lChild));
            printf("输入%d的右子节点:",ch);
            CreateBiTree((&(*T)->rChild));
        }
    }
    
    return 1;
}

DFS

void PreOrderBiTree(BiTNode *T)
{
    if (T == NULL)
    {
        return;
    }
    else
    {
        printf("%d ",T->data);
        PreOrderBiTree(T->lChild);
        PreOrderBiTree(T->rChild);
    }
}
void MiddleOrderBiTree(BiTNode *T)
{
    if (T == NULL)
    {
        return;
    }
    else
    {
        MiddleOrderBiTree(T->lChild);
        printf("%d ",T->data);
        MiddleOrderBiTree(T->rChild);
    }
}
void PostOrderBiTree(BiTNode *T)
{
    if (T == NULL)
    {
        return;
    }
    else
    {
        PostOrderBiTree(T->lChild);
        PostOrderBiTree(T->rChild);
        printf("%d ",T->data);
    }
}


BFS

/*
思路:遍历二叉树的第k层,相当于遍历二叉树根节点的左右子树的第k-1层。这样一直遍历下去,直到k=0时,输出节点即可。
*/
int PrintNodeAtLevel(BiTNode *root, int level)
{
    if(!root || level < 0)
        return 0;
    else if(level == 0)
    {
        printf("%d ",root->data);
        return 1;
    }
    else
        return PrintNodeAtLevel(root->lChild, level - 1) + PrintNodeAtLevel(root->rChild, level - 1);
}
//层次遍历----根据求得的层次,遍历每一层
void TranverseTree1(BiTNode *root)
{
    for(int i = 0; i < TreeDeep(root); ++i)
    {
        PrintNodeAtLevel(root, i);
        printf("\n");
    }
}
//层次遍历----无需求得层次,根据遍历每层的返回信息确定遍历
void TranverseTree2(BiTNode *root)
{
    for(int i = 0; ; ++i)
    {
        if(!PrintNodeAtLevel(root, i))
            break;
        printf("\n");
    }
}

思路:二叉树的层次遍历思路,借助队列来实现。相当于广度优先搜索,使用队列(深度优先搜索的话,使用栈)。

1. 若根节点为空,直接返回;
2. 若根节点非空,则将根节点入队,然后,判断队列是否为空;若不为空,则将队首节点出队,访问,并判断其左右子节点是否为空,若不为空,则压入队列。
3. 因最终输出是从最后一层到第一层的输出,所以,直接调用reverse()函数,将整个容器翻转就可以了。

int TreeDeep(BiTNode *T)
{
    int deep = 0;
    if (T != NULL)
    {
        int leftdeep = TreeDeep(T->lChild);
        int rightdeep = TreeDeep(T->rChild);
        deep = leftdeep >= rightdeep?leftdeep+1:rightdeep+1;
    }
    
    return deep;
}
int LeafCount(BiTNode *T)
{
    static int count;
    if (T != NULL)
    {
        if (T->lChild == NULL && T->rChild == NULL)
        {
            count++;
        }
        
        LeafCount(T->lChild);
        LeafCount(T->rChild);
    }
    
    return count;
}

//二叉树翻转
/*
算法原理:

在数据结构中,对于树这种结构,我们经常采用的策略是使用递归的方式,在这里,我们也使用递归来解决这个问题。

递归算法步骤:

    1、对二叉树的左子树进行翻转

    2、对二叉树的右子树进行翻转

    3、将左右子树的根节点进行交换(不用考虑原二叉树的根节点,因为原二叉树的根节点在翻转前后没有改变)
*/

BiTNode* InvertBinaryTree(BiTNode *tree) {
    if (NULL == tree) {
        return NULL;
    }

    tree->lChild = InvertBinaryTree(tree->lChild);
    tree->rChild = InvertBinaryTree(tree->rChild);
    
    BiTNode *tempTree = tree->lChild;
    tree->lChild = tree->rChild;
    tree->rChild = tempTree;
    return tree;
}
//根据先序遍历序列和中序遍历序列重建二叉树
BiTree Construct(int *ptree,int *itree,int length)
{
    if(ptree==NULL || itree==NULL || length<=0)
        return NULL;
    return ConstructCode(ptree,ptree+length-1,itree,itree+length-1);
}

/****************************************************************
 *args:
 *   ptree_start:先序遍历开始位置指针
 *   ptree_end:先序遍历结束位置指针
 *   itree_start:中序遍历开始位置指针
 *   itree_end:中序遍历结束位置指针
 ****************************************************************/
BiTree ConstructCode(int *ptree_start,int *ptree_end,int *itree_start,int *itree_end)
{
    BiTree root_node;
    root_node=(BiTree)malloc(sizeof(BiTNode));
    root_node->data=ptree_start[0];                          /*根节点*/
    root_node->lChild=NULL;
    root_node->rChild=NULL;
    
    if(ptree_start==ptree_end)                              /*该节点是子树最后一个节点*/
    {
        if(itree_start==itree_end && *ptree_start==*ptree_end)
        {
            return root_node;
        }else
        {
            printf("ConstructCode is error!\n");
            exit(1);
        }
    }
    int *tmp_itree=itree_start;
    int left_length=0;
    while((*itree_start!=root_node->data) && (itree_start<itree_end))/*在中序遍历中寻找跟节点的指针*/
    {
        itree_start++;
    }
    left_length=itree_start-tmp_itree;                      /*根节点在中序遍历中的位置,用于求在先序遍历中右子树的开始位置*/
    if(left_length>0)                                        /*左子树递归*/
    {
        root_node->lChild=ConstructCode(ptree_start+1,ptree_start+left_length,tmp_itree,itree_start-1);
    }
    if(left_length<(ptree_end-ptree_start))                  /*右子树递归,pend-pstart>left_length说明遍历序列比左子树长,右子树有节点*/
    {
        root_node->rChild=ConstructCode(ptree_start+left_length+1,ptree_end,itree_start+1,itree_end);
    }
    return root_node;
}

非标准答案,改中序遍历,添加标记打印。

二叉树结构

//中序遍历 找出节点的下一个节点
void MiddleOrderBiTreeFindNextData(BiTNode *T,int s,int flag)
{
    if (T == NULL)
    {
        return;
    }
    else
    {
        MiddleOrderBiTreeFindNextData(T->lChild,s,flag);
        if (flag == 1) {
            printf("%d ",T->data);
            return;
        }
        if (T->data == s) {
            flag = 1;
        }
        MiddleOrderBiTreeFindNextData(T->rChild,s,flag);
    }
}

and so on...

上一篇 下一篇

猜你喜欢

热点阅读