美文网首页
链表和二叉树

链表和二叉树

作者: 闫品品 | 来源:发表于2019-07-05 10:14 被阅读0次

    单向链表

    typedef struct list_node *list_pointer;
    typedef struct list_node{
            int data;
            list_pointer link;
    }
    

    链表反转

    list_pointer invert(list_pointer lead){
        list_pointer mid, tail;
        mid = NULL;
        while(lead){
            tail = mid;
            mid = lead;
            lead = lead->link;
            mid->link = tail;
        }
        return mid;
    }      
    

    二叉树定义

    typedef struct node *tree_pointer;
    typedef struct list_node{
        int data;
        tree_pointer left, right;
    }
    

    1、递归中序遍历

    void inorder(tree_pointer ptr){
        if(ptr){
            inorder(ptr->left);
            printf("%d", ptr->data);
            inorder(ptr->right);
        }
    }
    

    2、迭代中序遍历

    void iter_inorder(tree_pointer ptr){
        int top = -1;
        tree_pointer stack[MAX_STACK_SIZE];
        for(;;){
            for(; ptr; ptr = ptr->left){
                add(&top, ptr);
            }
            ptr = delete(&top);
            if(!ptr)
                break;
            printf("%d", ptr->data);
            ptr = ptr->right;
        }
    }
    

    3、二叉树层序遍历

    void level_order(tree_pointer ptr){
        int front = rear = 0;
        tree_pointer queue[MAX_QUEUE_SIZE];
        if(!ptr)
            return;
        addQueue(front, &rear, ptr);
        for(;;){
            ptr = deleteQueue(&front, rear);
            if(ptr){
                if(ptr->left)
                    addQueue(front, &rear, ptr->left);
                if(ptr->right)
                    addQueue(front, &rear, ptr->right);            
            }
            else
                break; 
        }
    }
    

    4、判断一棵树是否为平衡树
    思路一:按照前序遍历的路线判断。
    1.判断以根结点的树是否为二叉平衡树。求出左右子树的高度,判断它们的高度差是否超过了1。
    2.递归判断根的左子树是否为平衡二叉树
    3.递归判断根的右子树是否为平衡二叉树
    注意:空树也是平衡二叉树

    //二叉树的高度(比较左右子树那个高,高的加1既为二叉树的高度)
    int BinaryTreeHigh(tree_pointer ptr)
    {
        if (root == NULL)
        {
            return 0;
        }
        int ret1 = BinaryTreeHigh(ptr->_left);
        int ret2 = BinaryTreeHigh(ptr->_right);
        //二叉树的高度为左子树和右子树中高的那个高度加1
        return ret1 > ret2 ? ret1 + 1 : ret2 + 1;
    }
    //判断树是否为平衡二叉树(1:是 0:不是)
    int IsBlancedTree_R(tree_pointer ptr)
    {
        //空树是平衡二叉树
        //平衡二叉树是指以当前结点为根的左右子树高度不得超过1
        if (ptr == NULL)
            return 1;
        //右子树深度
        int right = BinaryTreeHigh(ptr->_left);
        //左子树深度
        int left = BinaryTreeHigh(ptr->_right);
        int gap = right - left;
        //深度超过1不是
        if (gap > 1 || gap < -1)
            return 0;
        //递归判断子树
        return IsBlancedTree_R(ptr->_left) && IsBlancedTree_R(ptr->_right);
    }
    

    思路二:按照后序遍历的路线判断
    1.首先,判断它的左子树是否为平衡二叉树
    2.然后在判断它的右子树是否为平衡二叉树
    3.判断它们是否为平衡二叉树的同时,记录它们的左右子树的深度
    4.最后在判断以这个结点为根的树是否为平衡二叉树

    /判断树是否为平衡二叉树(1:是 0:不是)
    //优化版本(不用遍历重复的结点)
    int IsBlancedTree_op(tree_pointer ptr, int *pdepth)
    {
        if (ptr == NULL)
        {
            *pdepth = 0;
            return 1;
        }
        //按照后序遍历去判断,先判断左右子树,然后记录以当前结点为根树的深度
        int left, right;
        if (IsBlancedTree_op(ptr->_left, &left) && IsBlancedTree_op(ptr->_right, &right))
        {
            int gap = right - left;
            if (gap <= 1 && gap >= -1)
            {
                *pdepth = left>right ? left + 1 : right + 1;
                return 1;
            }
        }
        return 0;
    }
    

    5、二叉树最小公共父节点

    tree_pointer  lowestCommonAncestor(tree_pointer ptr, tree_pointer p, tree_pointer q){
        if(!ptr || ptr == p|| ptr == q)
            return ptr;
        TreeNode left = lowestCommonAncestor(ptr->left, p, q);
        TreeNode right = lowestCommonAncestor(ptr->right, p, q);
        if(left&&right)
            return root;
        if(!left)
            return right;
        if(!right)
            return left;
    }
    

    6、判断二叉树是否对称

    bool balance_tree(tree_pointer ptr){
        flag=0;
        while(p!=NULL)
        {
            if(p->left == NULL && p->right)
            {
                return(0);
            }
            if(p->rchild==NULL){
                flag = 1;
            }
            if(flag == 1 && p->left != NULL || p->right != NULL){
                return 0;
            }
        }
        return 1;
    }
    

    7、将二叉树转为排序双向链表
    要点:

    1.直接改变树的结构

    2.排序二叉树在中序遍历的时候是有序的

    3.双向链表,需要前后两个指针(可以将Tree的节点作为链表节点)

    代码实现:中序的递归实现

    void ToList(Tree* pTree ,Tree** pHead,Tree** pEnd )
    {
        if(pTree == NULL ) return;
        ToList(pTree->pleft,pHead,pEnd);
        if(*pHead == NULL)
        {
            *pHead = pTree;
            *pEnd = pTree;
        }
        else
        {
            (*pEnd)->pright = pTree;
            pTree->pleft = *pEnd;
        }
        (*pEnd) = pTree;
        ToList(pTree->pright,pHead,pEnd);
    }
    

    相关文章

      网友评论

          本文标题:链表和二叉树

          本文链接:https://www.haomeiwen.com/subject/ylfshctx.html