二叉排序树的插入与遍历(例子是九度1201题)

来源:互联网 发布:无人机摄影测量软件 编辑:程序博客网 时间:2024/06/04 17:45

    二叉树和二叉排序树啥啥的在上数据结构这门课时就没搞懂,时隔两年再看时突然莫名顿悟了一些,特写此心得记录一下,如果有什么地方理解出错了,请留言纠正,谢谢。

    二叉排序树是一种特殊的二叉排序树,满足如下条件:对于树上任意一个结点,其上的数值必大于等于其左子树上任意结点的数值,必小于等于其右子树上任意结点的数值。

    二叉树的插入:1、若目前树为空,则插入第一个数,作为根节点。2、目前树不为空,则从根节点开始比较,若小于(等于)根结点,且根节点左孩子为空,则插入第二个数作为根节点的左孩子;若不为空,则与根节点的左孩子比较。若大于(等于)根结点,且根节点右孩子为空,则插入第二个数作为根节点的右孩子;若不为空,则与根节点的右孩子比较。3、每插入一个数都是从根节点开始比较,重复2的步骤直到插入结束。(括号中的等于根据不同题目要求具体看是否要包括等于的情况)

    由于各个数字的插入顺序不同,所得的二叉排序树的形态也很可能不同。但是,所有的二叉排序树的中序遍历都是一个递增的序列,通过建立二叉排序树就能对原无序序列进行排序,并实现动态维护

    二叉树的遍历遍历分为三种,先序遍历、中序遍历、后序遍历。先序遍历是按照根左右的顺序,中序是左根右,后序是左右根,个人感觉看代码更容易理解遍历的实现过程,语文不好难以描述┑( ̄Д  ̄)┍

    借助例子来看看吧(借用九度1201题二叉排序树)

    题目描述:

         输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历。

    输入:

         输入第一行包括一个整数n(1<=n<=100)。
         接下来的一行包括n个整数。

    输出:

         可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,并对二叉排序树进行前序、中序和后序遍历。
         每种遍历结果输出一行。每行最后一个数据之后有一个空格。

    样例输入:
51 6 5 9 8
    样例输出:
1 6 5 9 8 1 5 6 8 9 5 8 9 6 1 
提示:

输入中可能有重复元素,但是输出的二叉树遍历序列中重复元素不用输出。

#include<stdio.h>#include<stdlib.h>#include<string.h>struct node   //定义节点的结构体{node *lchild;   //左孩子node *rchild;   //右孩子int c;    //节点的数值}tree[201]; /*数据采用全局变量节省了函数间互相传参的麻烦,不过也要慎用*/int loc;   //loc表示申请了空间的节点的个数node *t;    //构建的二叉排序树node *ret;   //当前申请空间的节点node* create()     //结点的空间申请函数,返回该节点对应的结构体指针{tree[loc].lchild = tree[loc].rchild = NULL;    //初始化左右子树为空return &tree[loc++];     //返回指针后,loc再++}void build(node *k,int s){      if (s < k->c)   //从根节点开始比较{if (k->lchild == NULL)  //如果比较的节点的左孩子为空{ret = create();  //则创建新节点,并作为该节点的左孩子ret->c = s;k->lchild = ret;}else               //如果左孩子不为空,则递归访问节点的左孩子{build(k->lchild,s);}}else if (s > k->c)   //大于的情况与小于相似,就不赘述了{if (k->rchild == NULL){ret = create();ret->c = s;k->rchild = ret;}else{build(k->rchild,s);}}}void inorder(node *t)   //先序遍历{printf("%d ", t->c);   //遍历该结点,输出其字符信息if (t->lchild != NULL)   //若左子树不为空{inorder(t->lchild);    //递归遍历其左子树}if (t->rchild != NULL)   //若右子树不为空{inorder(t->rchild);    //递归遍历其右子树}}void midorder(node *t)  //中序遍历{if (t->lchild != NULL)   //若左子树不为空{midorder(t->lchild);    //递归遍历其左子树}printf("%d ", t->c);    //遍历该结点,输出其字符信息if (t->rchild != NULL)   //若右子树不为空{midorder(t->rchild);    //递归遍历其右子树}}void postorder(node *t)    //后序遍历{if (t->lchild != NULL)   //若左子树不为空{postorder(t->lchild);    //递归遍历其左子树}if (t->rchild != NULL)   //若右子树不为空{postorder(t->rchild);    //递归遍历其右子树}printf("%d ", t->c);    //遍历该结点,输出其字符信息}int main(){int i,n,arr[201];   //n为节点个数,arr为所有节点数值的数值,也可采用动态数组while (scanf("%d",&n)!=EOF)  //因为输入可能包含多组数据,重复读入n,直到n为文件结束符{for (i = 0; i < n; i++)scanf("%d", &arr[i]);  //读入节点的数值loc = 0;t = create();  //创建根节点t->c = arr[0];for (i = 1; i < n; i++)   //从第二个数值开始插入build(t,arr[i]);   inorder(t);  //先序遍历printf("\n"); midorder(t);  //中序遍历printf("\n");postorder(t);  //后序遍历printf("\n");}return 0;}

由于数字插入顺序不同会导致二叉排序树的不同,但这种情况下的中序遍历是相同的,所以需要中序遍历+先序遍历 或 中序遍历+后序遍历才能确定唯一的二叉树。


0 0