• 二叉树的性质:

    (1)二叉树的第i(i≥1)层最多有2^(i-1)个结点.

    (2)深度为k(根节点的深度为1)的二叉树最多有2^k-1个结点.

    (3)叶子的数目=度为2的结点数目+1.

    满二叉树的性质:

    (1)n个结点的满二叉树的深度=log2(n+1)

    (2)顺序编号的满二叉树的性质:结点i的左小孩是结点2i;结点i的右小孩是结点2i+1;结点i的双亲是结点int(i/2);结点i的层号int(log2 i)+1.

    完全二叉树:

    深度为k的有n个结点的二叉树,当且仅当每一个结点都与同深度的满二叉树中编号从1至n的结点一一对应。

    二叉搜索树:

    左子结点总是小于根结点,右子结点总是大于根结点。用中序遍历得到的结果是从小到大排序的。

    面试题:3种遍历的6种实现方法;广度优先与深度优先;堆与红黑树

    13种遍历的6种实现方法

    #include<stdio.h>       //printf,scanf需要的头文件
    #include<stdlib.h>     //malloc需要的头文件
    #include "conio.h"       //exit需要的头文件
    
    typedef struct BiTNode{
        char data;
        struct BiTNode *lchild,*rchild;
    }BiTNode,*BiTree;
    //前序遍历
    void PreOrderTraverse(BiTree T)
    {
        if(T==NULL)
            return;
        printf("%c",T->data);
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
    
    //中序遍历
    void InOrderTraverse(BiTree T)
    {
        if(T==NULL)
            return;
        InOrderTraverse(T->lchild);
        printf("%c",T->data);
        InOrderTraverse(T->rchild);
    }
    
    //后序遍历
    void PostOrderTraverse(BiTree T)
    {
        if(T==NULL)
            return;
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        printf("%c",T->data);
    }

     前序遍历的非递归算法思路:从根节点开始,输出当前结点。遇到左结点不为空的情况,就输出当前结点,并把结点压栈。如果左结点为0,就转而搜索它的右结点,并把该结点出栈,说明该结点的左右结点已经全部被搜索过了。如果所有结点的左右结点结点都被搜索过,则搜索结束。

              或者:首先将根结点入栈。弹出栈顶结点,输出结点值。将当前结点的右结点入栈,再将左结点入栈。循环知道栈为空。

    中序遍历的非递归算法思路:从根结点开始,把当前结点压栈。如果其左结点存在,就把左结点压栈,继续向左搜索。遇到其左结点不存在的情况,输出当前结点值后,转而搜索它的右结点。并且要把该结点出栈,证明当前结点及左右结点都已经被访问过。

    后续遍历的非递归算法思路:从根结点开始,把当前结点压栈。如果当前结点没有子节点或者是子节点已经被访问过了,则输出该结点的值,并且将该结点出栈。否则,如果它的左结点或者右结点存在,则按先右后左的方式压栈。

    //前序遍历非递归
    void PreOrderTraverse_t(BiTree T)
    {
        stack<BiTNode*> s;
        BiTNode* p=T;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                printf("%c",p->data);
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                p=p->rchild;
            }
        }
    }
    
    //中序遍历非递归
    void InOrderTraverse_t(BiTree T)
    {
        stack<BiTNode*> s;
        BiTNode* p=T;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                printf("%c",p->data);
                p=p->rchild;
            }
        }
    }
    
    //后续遍历非递归
    void PostOrderTraverse_t(BiTree T)
    {
        stack<BiTNode*> s;
        BiTNode* cur=T;
        BiTNode* pre=NULL;
        s.push(T);
        while(!s.empty())
        {
            cur=s.top();
            if((cur->lchild==NULL&&cur->rchild==NULL)||(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))  //如果当前点没有做结点并且没有右结点,或者是左右结点被访问过,则输出当前结点的值
            {
                printf("%c",cur->data);      //如果pre==cur->rchild,可以cur可以被输出了,因为如果一个点的右支已经被输出过了,就应该立刻输出当前点了。如果pre==cur->lchild,是因为右支不存在。左支已输出,并且右支不存在的情况下,则将当前点输出。
                s.pop();
                pre=cur;
            }                         //否则,左右支不全为空或者pre!=cur->lchild&&pre!=cur->rchild的情况下,说明当前结点的左右子结点还没有被访问过,则应该继续入栈。
    else        
            {
                if(cur->rchild!=NULL)
                    s.push(cur->rchild);
                if(cur->lchild!=NULL)
                    s.push(cur->lchild);
            }
        }
    }

     2.广度搜索与深度搜索

     广度优先搜索:层序遍历。按每一层从左到右的顺序输出。

    用队列的思想来解决:将根结点压入队列。如果队列不为空,弹出队列的首结点,并输出该结点。如果该结点的左右子结点存在,就把左右结点依次压入队列中。

    //层序遍历。用队列的思想解决
    void LevelOrderTraverse(BiTree T)
    {
        if(T==NULL)
            return;
        queue<BiTNode*> q;
        q.push(T);
        while(q.size())
        {
           BiTNode* pNode=q.front();
           q.pop();
           printf("%c",pNode->data);
           if(pNode->lchild!=NULL)
               q.push(pNode->lchild);
           if(pNode->rchild!=NULL)
               q.push(pNode->rchild);
        }
    }

    深度优先搜索:就是前序遍历。

    3.根据前序遍历结果和中序遍历结果构建二叉树(剑指offer面试题6)

    思想:前序遍历的第一个点是根结点。在中序遍历中,根结点左边的为左子树的中序遍历结果,根结点右边的为右子树的中序遍历结果。中序遍历左子树结点的个数N_left,右子树的结点为N_right。那么在前序遍历结果中,紧挨着跟结点的N_left个结点为左字数的前序遍历结果,剩下的为右子树的前序遍历结果。然后递归分别构建左子树和右子树。

  • 相关阅读:
    算法25-----位运算(2)-----案例
    算法24----重复子字符串
    算法23-------岛屿的最大面积 LeetCode 695
    算法22-----托普利茨矩阵leetcode766
    算法21----重塑矩阵 LeetCode566
    Python笔记25-----------创建二维列表【浅copy】和转置
    TensorFlow+实战Google深度学习框架学习笔记(7)-----队列与多线程
    TensorFlow+实战Google深度学习框架学习笔记(6)----神经网络经典损失函数
    Testing
    Spark简介
  • 原文地址:https://www.cnblogs.com/wy1290939507/p/4677592.html
Copyright © 2020-2023  润新知