二叉树的几个基本算法

来源:互联网 发布:知乎启动画面 编辑:程序博客网 时间:2024/06/11 12:59

二叉树的基本算法

1.二叉树的基本遍历算法(先序、中序、后序、层序)

2.二叉树的优化遍历算法(用栈实现)

3.求二叉树的深度算法

4.求二叉树的宽度算法

5.二叉树的构建算法


#include <stdio.h>#include <stdlib.h>/** *   二叉树的基本算法*   1.二叉树的基本遍历算法(先序、中序、后序、层序)*   2.二叉树的优化遍历算法(用栈实现)*   3.求二叉树的深度算法*   4.求二叉树的宽度算法*   5.二叉树的构建算法**/typedef struct BTNode{    int data;    struct BTNode * lchild;    struct BTNode * rchild;}BTNode;/***   二叉树的三种遍历算法*   1.先序、中序、后序、层序*///先序void Trave1(BTNode * root){    if(root != NULL){        printf("%d",root->data);        Trave1(root ->lchild);        Trave1(root ->rchild);    }}//中序void Trave2(BTNode * root){    if(root != NULL){        Trave2(root ->lchild);        printf("%d",root->data);        Trave2(root -> rchild);    }}//后序void Trave3(BTNode * root){    if(root != NULL){        Trave3(root->lchild);        Trave3(root->rchild);        printf("%d",root->data);    }}#define maxSize 100//二叉树的层序列遍历void Trave4(BTNode * root){    //用一个队列辅助遍历二叉树,左孩子和右孩子分别入队      BTNode * que[maxSize];    int front = 0,rear = 0;    if(root != NULL){        //根结点入队        rear = (rear + 1)%maxSize;        que[rear] = root;        while(front != rear){//队列不空则循环            //出队            front = (front +1)%maxSize;            printf("%d",que[front]->data);            //左右孩子进栈            if(que[front]->lchild != NULL){                rear = (rear + 1)%maxSize;                que[rear] = que[front]->lchild;            }            if(que[front]->rchild != NULL){                rear = (rear + 1)%maxSize;                que[rear] = que[front]->rchild;            }        }    }   }/***   二叉树的构建算法,通过'-1'表示结尾*   思路:每次构建完成一个结点,返回结构体指针*/BTNode * createTree(){    printf("请输入一个结点作为二叉树的一个结点\n");    int data;    scanf("%d",&data);    if(data == -1){        return NULL;    }else{        BTNode * root = (BTNode *)malloc(sizeof(BTNode));        root->data = data;        root -> lchild = createTree();        root -> rchild = createTree();        return root;    }}/***   求二叉树的深度算法*   思路:分别求二叉树的左右子树的深度,然后再加+1就是总深度,用递归算法即可完成*/int getDepth(BTNode * root){    int ldepth,rdepth;    if(root == NULL){        return 0;    }else{        ldepth = getDepth(root->lchild);        rdepth = getDepth(root->rchild);        return (ldepth>rdepth?ldepth:rdepth) + 1;    }}/***   求二叉树的宽度算法*   思路:用层序遍历,将二叉树每层都标上号码,然后用迭代对其进行求最大值*       标号的方式,这里我采用构建一个新的结构体,并定义一个队列数组来进行对每个结点标号*       并且假设这个数组能够容纳下所有结点,这样才能方便在后面的迭代中求最大值*/typedef struct{    BTNode * node;    int flag;   //层号从1开始到n}ST;int getWidth(BTNode * root){    //先构建一个顺序队列    ST * que[maxSize];    int front=0,rear=0;    int flag = 1;    if(root != NULL){        //根节点入队,并标号为1,表示第1层        ST * p = (ST *)malloc(sizeof(ST));        p->flag = flag;        p->node = root;        rear ++;            que[rear] = p;          BTNode * q;        while(root != NULL){            front ++;   //这里出队,但是数据元素还是在数组中            q = que[front]->node;            if(que[front]->flag > flag){    //证明到达了下一层,那么flag也要增加,这里改写层flag = que[front]->flag也可以                flag ++;                }            if(que[front]->node->lchild != NULL){   //左孩子不空,则左孩子入队                rear ++;                /*                que[rear]->node = q->lchild;                que[rear]->flag = flag + 1;                */                p = (ST *)malloc(sizeof(ST));                p->node = q->lchild;                p->flag = flag + 1;                que[rear] = p;            }            if(que[front]->node->rchild != NULL){                rear ++;                /*                que[rear]->node = q->rchild;                que[rear]->flag = flag + 1;                */                p = (ST *)malloc(sizeof(ST));                p->node = q->rchild;                p->flag = flag + 1;                que[rear] = p;            }        }        //下面求二叉树的最大宽度        int i,j,max=0;        for(i=1;i<=flag;i++){            int n=0;            for(j=1;j<=rear;j++){                if(que[j]->flag == i){                    n++;                }            }            if(max<n){                max = n;            }        }        return max;    }    return 0;}//不使用指针数组int getWidth2(BTNode * root){    ST que[maxSize];    int flag = 1;    int front=0,rear=0;    if(root !=NULL){        rear ++;        que[rear].node = root;        que[rear].flag = flag;        BTNode * q;        while(front != rear){            front ++;            q = que[front].node;            flag = que[front].flag;            if(q->lchild != NULL){                rear ++;                que[rear].node = q;                que[flag].flag = flag + 1;            }            if(q->rchild != NULL){                rear ++;                que[rear].node = q;                que[flag].flag = flag + 1;            }        }        int max,n,i,j;        for(i=1;i<=flag;i++){            n = 0;            for(j=1;j<=flag;j++){                       if(que[j].flag == i){                    n++;                }            }            if(max<n){                max = n;            }        }        return max;    }    return 0;}/***   用栈实现二叉树的先序遍历*   思路:先序遍历的特点是遇到就输出,分别遍历其左右子树*/void traveByStack(BTNode * root){    BTNode * stack[maxSize];    BTNode * p;    int top = -1;    if(root != NULL){        //根节点入栈        stack[top] = root;        while(top != -1){   //栈不空则循环            //出栈            p = stack[top--];            printf("%d",p->data);            if(p->rchild!=NULL){//右孩子不空,则右孩子入栈                stack[++top] = p->rchild;            }            if(p->lchild!=NULL){//左孩子不空,则左孩子入栈,这里顺序跌倒的原因是因为在栈的输出中顺序是相反的                stack[++top] = p->lchild;            }        }    }}/***   用栈实现二叉树的中序遍历*   思路:中序的实现根先序列有点不一样,不一样的地方在于,中序需要让左孩子先全进栈,直到没有左孩子就出栈并输出*       出栈之后,将指针移向右孩子,那么就看他有没有右孩子,如果有右孩子,右孩子入栈,重复上面的操作*       否则,就回滚,注意,回滚之后,循环条件又会判断是否还有左孩子,那么由于之前的指针是指向的p的右孩子,所以,这里*       循环进入不了,直接判断是否栈空,栈不空就出栈,并让指针指向出栈元素的右孩子*/void traveByStack2(BTNode * root){    BTNode * stack[maxSize];    int top = -1;    BTNode * p = root;    //根结点入栈    if(root != NULL){        /*  由于下面的循环写成  || p != NULL 所以这里可以省略            //写||p!=NULL的主要原因是如果所有结点都是右孩子结点,那么可能存在的问题的是可能不满足第二次循环的条件了        stack[++top] = p;        p=p->lchild;        */        while(top!=-1||p!=NULL){    //这里加上||p!=null的原因是有可能p永远都是右孩子,那么在执行第一次循环就结束了,所以要加上            while(p!= NULL){//如果左孩子不为空,那么左孩子就一直进栈                stack[++top] = p;                p=p->lchild;            }            //没有左孩子了就出栈,并让指针指向该结点的右孩子            printf("%d",stack[top]->data);            p = stack[top--]->rchild;            printf("%d",p->data);        }       }}int main(){    printf("程序开始\n");    BTNode * p;    p = createTree();    int width = getWidth2(p);    printf("%d",width);    return 0;}
原创粉丝点击