如何利用前序遍历序列和中序遍历序列非递归的创建二叉树

来源:互联网 发布:python idle打开闪退 编辑:程序博客网 时间:2024/06/05 10:18

  说到二叉树的创建,我们一般会想到用递归的方法,因为利用递归写的代码看起来很简洁,但是递归的使用也同样存在效率不够高的问题。所以这里我们要说的是如何利用前序遍历序列和中序遍历序列非递归的创建二叉树。
  思想:利用两个栈实现(当然也可以用一个栈,这里针对自己的数据类型设计),一个栈s用来存放树的各个结点,另一个栈isindex用来存放第一个栈中元素对应于中序序列中的下标。首先,我们先将根结点(即前序序列中的第一个元素)及其在中序序列中相应的下标分别入栈s和isindex,并将根结点置于当前结点。然后,从前序序列中首元素开始,依次比较相邻两个元素在中序序列中对应的下标,来确定后一个元素是当前结点的左子树还是右子树,具体有以下几种情况:
    1. index2 == -1 这是在中序序列中没找到前序序列中的元素,说明是遍历序列有问题,直接退出
    2. index1 > index2 前序序列中后一个元素在中序序列中相对较前的位置,说明后一个元素是当前结点的左子树
    3. index1 < index2 前序序列中后一个元素在中序序列中相对较后的位置,说明后一个元素是当前结点的右子树,至于是那棵右子树,还需对index2和栈isindex栈顶元素作循环比较
   说到这里就有一个疑问了:为什么index2要和isindex栈顶元素比较呢?首先我们得知道isindex2里面存的是什么,前面已经说过,isindex里面存的是已经创建好的部分树的结点在中序序列中的下标,根据中序遍历的特点:中序遍历左子树,访问根节点,中序遍历右子树,我们知道,中序序列中右结点总是在左结点以及根结点的后边,即右结点在中序序列中的下标要大于左结点和根结点的下标,所以要想知道index2所对应的元素是已创建好的部分树的哪一个结点的右孩子结点,我们需要循环比较index2和栈isindex的栈顶元素的结点,如果栈顶元素较index2小,则栈s和isindex同时出栈,并将出栈结点作为当前结点,直到两栈为空或者遇到第一个比index2大的元素(即我们循环的目的就是找到最后一个比index2小的元素,这样index2所对应的元素就是找到的元素的右孩子结点),此时index2对应的元素就是当前结点的右孩子结点。
   那么index1==index2这种情况有没有可能出现呢?在这里我们一般不考虑重结点的情况,所以这种情况不会出现。

   
变量说明
ps 前序序列指针
is 中序序列指针
s 栈,存放树的各个结点
isindex 利用数组模拟的栈,用来存放栈s中对应元素在中序序列中的下标
index1 前序序列中前一个元素在中序序列中的下标
index2 前序序列中后一个元素的中序序列中的下标
参考代码:“

typedef char ElemType;typedef struct btnode   //二叉树的结点定义{    ElemType data;    btnode *leftchild;    btnode *rightchild;}BtNode,*BtTree; //在中序序列中查找元素函数int find (char *is,char ch){    if (is == NULL)    {        exit (1);    }    int i = 0;    while (is[i] != 0)    {        if (is[i] == ch)        {            return i;        }        else        {            i ++;        }    }    return -1;}BtNode *NiceCreatTreePI (char *ps,char *is){    if (NULL == ps && NULL == is)    {        return NULL;    }    int isindex[MAXSIZE] = {0};     //用数组模拟一个顺序栈 (从数组最后入栈和出栈)    for (int j = 0;j < MAXSIZE;j ++)    //初始化全用-1表示,以便出栈处理    {        isindex[j] = -1;    }    int i = 0;    SeqStack s;    Init_stack (&s);    BtNode * p = BuyNode ();    p -> data = *ps;    Push (&s,p);    BtNode *child = NULL;    BtNode *tree = p;    int index1 = find (is,*ps);    isindex[i ++] = index1;    //相当于进栈    int index2 = index1;    while (*(ps + 1) != 0)    {        index1 = index2;             index2 = find (is,*(ps + 1));        if (index1 == -1 || index2 == -1)        {            exit (1);        }        if (index1 > index2)  //左子树        {            child = BuyNode ();            ps ++;            child -> data = *ps;            p -> leftchild = child;            p = p -> leftchild;            Push (&s,child);            isindex[i ++] = index2;                 }        else     //右子树        {            i --;             while (i >= 0 && index2 > isindex[i])            {                p = top (&s);                pop (&s);                isindex[i] = -1;                i --;            }            child = BuyNode ();            ps ++;            child -> data = *ps;            p -> rightchild = child;             p = p -> rightchild;            Push (&s,child);            i ++;            isindex[i ++] = index2;        }    }    return tree;}    

本文如有需要改进的地方,还请各位大神指点。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩一年级数学学不好怎么办 孩子一年级数学学不好怎么办 小学一年级数学学不好怎么办 孩子一年级数学成绩不好怎么办 成绩差的孩子该怎么办 面对成绩差的孩子该怎么办 六年级数学成绩差该怎么办 孩子数学物理成绩差该怎么办 高三成绩很差该怎么办 孩子学习成绩差家长该怎么办 孩子一年级语文成绩不好怎么办 孩子上网成瘾不听父母话怎么办 10岁数学不开窍怎么办 孩子五年级数学不好怎么办 一岁宝宝难断奶怎么办 2岁宝宝断不了奶怎么办 快2岁宝宝不听话怎么办 2岁半的宝宝不听话怎么办 3岁宝宝哭闹不止怎么办 2岁宝宝爱打人怎么办 两周岁宝宝吃东西就吐怎么办 两周岁宝宝不爱吃饭怎么办 两周岁宝宝反复发烧怎么办 两周岁宝宝咳嗽厉害怎么办 2岁宝宝体内有火怎么办 4岁宝宝数都不会怎么办 两岁宝宝太撅怎么办 儿童晚上发烧白天不发烧怎么办 宝宝晚上睡觉认人怎么办 两岁宝宝尿裤子怎么办 分手了想和好怎么办说 2岁半宝宝胆小怎么办 1岁半宝宝胆小怎么办 分手了还是想他怎么办 两岁宝宝夜惊怎么办 孩子误吃了牙膏怎么办 孩子跳舞脸上的妆卸不掉怎么办 4周岁还不会说话怎么办 宝贝2岁多还不会说话怎么办 孩子20个月离婚怎么办 两个月宝宝闹夜怎么办