数据结构-二叉树的前序、中序、后序、层次遍历

一、基本概念

每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。

性质:

1、非空二叉树的第n层上至多有2^(n-1)个元素。

2、深度为h的二叉树至多有2^h-1个结点。

满二叉树:所有终端都在同一层次,且非终端结点的度数为2。

在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。

完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集中在左面的位置上,不能有空位置。

对于完全二叉树,设一个结点为i则其父节点为i/2,2i为左子节点,2i+1为右子节点。


二、存储结构

链式存储:

</pre><pre name="code" class="cpp">typedef char datatype;
typedef struct BinNode{
<span style="white-space:pre">	</span>datatype data;
<span style="white-space:pre">	</span>struct BinNode* lchild;
<span style="white-space:pre">	</span>struct BinNode* rchild;
}BinNode;
typedef BinNode* bintree;

三、二叉树的遍历

遍历即将树的所有结点访问且仅访问一次。按照根节点位置的不同分为前序遍历,中序遍历,后序遍历。

前序遍历:根节点->左子树->右子树

中序遍历:左子树->根节点->右子树

后序遍历:左子树->右子树->根节点

递归实现(以前序遍历为例,其他的只是输出的位置稍有不同)

void preorder(bintree t){  
    if(t){  
        cout<<t->data;  
        preorder(t->lchild);  
        preorder(t->rchild);  
    }  
}  
非递归的实现

1、前序遍历

void preorder_dev(bintree t){  
    seqstack s;  
    s.top = -1;     //因为top在这里表示了数组中的位置,所以空为-1  
    if(!t){  
        printf("the tree is empty\n");  
    }else{  
        while(t || s.stop != -1){  
            while(t){    //只要结点不为空就应该入栈保存,与其左右结点无关      
                  printf("%c ",t->data);  
                push(&s,t);  
                t= t->lchild;  
            }  
            t=pop(&s);  
            t=t->rchild;  
        }  
    }  
}  
  2、中序遍历

void midorder(bintree t){  
    seqstack s;  
    s.top = -1;  
    if(!t){  
        printf("the tree is empty!\n");  
    }else{  
        while(t ||s.top != -1){  
            while(t){  
                push(&s,t);  
                t= t->lchild;  
            }  
            t=pop(&s);  
            printf("%c ",t->data);  
            t=t->rchild;  
        }  
    }  
}  
3、后序遍历

  1. void postorder_dev(bintree t){  
  2.     seqstack s;  
  3.     s.top = -1;  
  4.     if(!t){  
  5.         printf("the tree is empty!\n");  
  6.     }else{  
  7.         while(t || s.top != -1){    //栈空了的同时t也为空。  
  8.             while(t){  
  9.                 push(&s,t);  
  10.                 s.tag[s.top] = 0;   //设置访问标记,0为第一次访问,1为第二次访问  
  11.                 t= t->lchild;  
  12.             }  
  13.             if(s.tag[s.top] == 0){  //第一次访问时,转向同层右结点  
  14.                 t= s.data[s.top];   //左走到底时t是为空的,必须有这步!  
  15.                 s.tag[s.top]=1;       
  16.                 t=t->rchild;  
  17.             }else {  
  18.                 while (s.tag[s.top] == 1){ //找到栈中下一个第一次访问的结点,退出循环时并没有pop所以为其左子结点  
  19.                     t = pop(&s);  
  20.                     printf("%c ",t->data);  
  21.                 }  
  22.                 t = NULL; //必须将t置空。跳过向左走,直接向右走  
  23.             }  
  24.         }  
  25.     }  
  26. }  

4、层次遍历:即每一层从左向右输出

元素需要储存有先进先出的特性,所以选用队列存储。

队列的定义:

#define MAX 1000  
  
typedef struct seqqueue{  
    bintree data[MAX];  
    int front;  
    int rear;  
}seqqueue;  
  
  
void enter(seqqueue *q,bintree t){  
    if(q->rear == MAX){  
        printf("the queue is full!\n");  
    }else{  
        q->data[q->rear] = t;  
        q->rear++;  
    }  
}  
  
bintree del(seqqueue *q){  
    if(q->front == q->rear){  
        return NULL;  
    }else{  
        q->front++;  
        return q->data[q->front-1];  
    }  
}
遍历实现

void level_tree(bintree t){  
    seqqueue q;  
    bintree temp;  
    q.front = q.rear = 0;  
    if(!t){  
        printf("the tree is empty\n");  
        return ;  
    }  
    enter(&q,t);  
    while(q.front != q.rear){  
        t=del(&q);  
        printf("%c ",t->data);  
        if(t->lchild){  
            enter(&q,t->lchild);  
        }  
        if(t->rchild){  
            enter(&q,t->rchild);  
        }  
    }  
}

5、利用前序遍历的结果生成二叉树

//递归调用,不存点,想的时候只关注于一个点,因为还会回来的,不要跟踪程序运行,否则容易多加循环  
  
void createtree(bintree *t){        
    datatype c;  
    if((c=getchar()) == '#')  
        *t = NULL;  
    else{  
        *t = (bintree)malloc(sizeof(BinNode));  
        (*t)->data = c;  
        createtree(&(*t)->lchild);  
        createtree(&(*t)->rchild);  
    }  
}  

6、二叉树的查找

bintree search_tree(bintree t,datatype x){  
    if(!t){  
        return NULL;  
    }  
    if(t->data == x){  
        return t;  
    }else{  
        if(!search_tree(t->lchild,x)){  
            return search_tree(t->rchild,x);  
        }  
        return t;  
    }  
}  

7、统计结点个数

int count_tree(bintree t){  
    if(t){  
        return (count_tree(t->lchild)+count_tree(t->rchild)+1);  
    }  
    return 0;  
}  

8、比较两个树是否相同
int is_equal(bintree t1,bintree t2){  
    if(!t1 && !t2){      //都为空就相等  
        return 1;  
    }  
    if(t1 && t2 && t1->data == t2->data){      //有一个为空或数据不同就不判断了  
        if(is_equal(t1->lchild,t2->lchild))  
            if(is_equal(t1->rchild,t2->rchild)){  
                return 1;  
            }  
    }  
    return 0;  
}  
9、求二叉树的深度

int hight_tree(bintree t){  
    int h,left,right;  
    if(!t){  
        return 0;  
    }  
    left = hight_tree(t->lchild);  
    right = hight_tree(t->rchild);  
    h = (left>right?left:right)+1;  
    return h;  
}  







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值