数据结构 - 树与二叉树基础算法(一)

203 阅读3分钟

二叉树的存储结构

顺序存储:使用数组存储二叉树,根据下标依次确定每个结点数值
最适合完全二叉树,一般二叉树会浪费大量空间
链式存储:

    trpedef struct BTNode
    {
        char data;
        struct BTNode *lchilde;
        struct BTNode *rchild;
    }

二叉树的遍历算法

先序遍历

    void preorder(BTNode *p)
    {
        if(p!=NULL)
        {
            Visit(p); // 访问p结点的函数,比如打印p对应数值
            preorder(p->lchild); // 先序遍历左子树
            preorder(p->rchild); // 先序遍历右子树
        }
    }

中序遍历

    void inorder(BTNode *p)
    {
        if(p!=NULL)
        {
            inorder(p->lchild);
            Visit(p);
            inorder(p->rchild);
        }
    }

后序遍历

    void postorder(BTNode *p)
    {
        if(p!=NULL)
        {
            postorder(p->lchild);
            postorder(p->rchild);
            Visit(p);
        }
    }

二叉树的深度

    int getDepth(BTNode *p)
    {
        int LD,RD; // 左子树深度,右子树深度
        if(p==NULL)
            return 0;
        else
        {
            LD=getDepth(p->lchild);
            RD=getDepth(p->rchild);
            return (LD>RD?LD:RD) + 1; // 取较高的子树并加1
        }
    }

查找结点

查找data域值等于key的结点是否存在,若存在,将q指向该结点,否则q赋值NULL

// 先序遍历,假设二叉树已存在且p指向其根节点
    void search(BTNode *p, BTNode *&q, int key) // 将q定义为引用型指针,因为q要改变
    {
        if(p!=NULL)
        {
            if(p->data==key)
                q=p;
            else
            {
                search(p->lchild, q, key);
                search(p->rchild, q, key);
            }
        }
    }

改进: 若在左子树找到满足条件结点,无须继续查找右子树,直接退出本层递归

    void search(BTNode *p, BTNode *&q, int key)
    {
        if(p!=NULL)
        {
            if(p->data==key)
                q=p;
            else
            {
                search(p->lchild, q, key);
                if(q==NULL)
                    search(p->rchild, q, key);
            }
        }
    }

输出先序遍历序列中第k个结点的值

    int n=0; // 计结点数
    void trave(BTNode *p, int k)
    {
        if(p!=NULL)
        {
            ++n;
            if(k==n)
            {
                cout<<p->data<<endl; // c++ 输出p->data这个变量加换行,同 printf("%s\n",p->data);
                return;
            }
            trave(p->lchild, k);
            trave(p->rchild, k);
        }
    }

层次遍历

思想:应用循环队列,先将头节点入队,然后出队,访问该结点并将左右子树根节点入队,反复直到队列为空为止

    void level(BTNode *p)
    {
        int front,rear;// 循环队列首位结点
        BTNode *que[maxsize];// 定义循环队列
        front=rear=0; // 初始化队列
        BTNode *q; // 定义q结点用来访问出队结点
        if(p!=NULL)
        {
            rear=(rear+1)%maxsize;
            que[rear]=p; // 头指针入队
            while(front!=rear) // 循环条件:队列不为空
            {
                front=(front+1)%maxsize;
                q=que[front]; // 队列头节点出队
                Visit(q);
                if(q->lchild!=NULL) // 若出队结点有左孩子,则入队
                {
                    rear=(rear+1)%maxsize;
                    que[rear]=q->lchild;
                }
                if(q->rchild!=NULL) // 若出队结点有右孩子,则入队
                {
                    rear=(rear+1)%maxsize;
                    que[rear]=q->rchild;
                }
            }
        }
    }

求二叉树宽度

具有结点数最多的那一层的结点数

    typedef struct{
        BTNode *p;
        int lno;
    }St;
    int maxNode(BTNode *b)
    {
        st que[maxsize]; // 定义一个队列
        int front,rear; // 首位指针
        int Lno=0,i,j,max=0; // Lno结点所在层数
        front=rear=0; // 初始化队列
        BTNode *q; // 定义结点q,用来读取出队结点的左右孩子
        if(b!=NULL)
        {
            ++rear; // 根节点入队
            que[rear].p=b;
            que[rear].lno=1;
            while(front!=rear) // 层次遍历循环条件
            {
                ++front;
                q=que[front].p;
                lno=que[front].lno; // 头节点出队
                if(q->lchild!=NULL) // 左孩子入队
                {
                    ++rear;
                    que[rear].p=q->lchild;
                    que[rear].lno=Lno+1; // 根据根节点确定孩子结点所在层数
                }
                if(q->rchild!=NULL) // 右孩子入队
                {
                    ++rear;
                    que[rear].p=q->rchild;
                    que[rear].lno=Lno+1;
                }
            } // 循环结束,Lno保存二叉树的最大层数
            max=0; // 寻找最多元素层的元素个数
            for(i=1;i<=Lno;++i) //Lno层
            {
                n=0;
                for(j=;j<rear;++j) // 遍历第i层元素在队列中的个数
                    if(que[j].lno==i)
                        ++n;
                    if(max<n)
                        max=n;
            }
            return max;
        }
        else return 0;
    }