js用递归遍历多维数组_数据结构实验:树(5) || 非递归后序先序遍历,通过后序中序序列求先序层序...

这一篇用来补充一些作业中的代码。

Ⅰ 先序和后序遍历二叉树的非递归(栈)算法

先序遍历二叉树的栈算法

int PreOrderTraverse(BiTNode *T){    initstack(s); //初始化一个栈s    push(s, T);    visit(T);    BiTNode *p = T;    while (!stackempty(s))    {        while (gettop(s, p) && p)        {            visit(p);            push(s, p->lchild);        }          //先序走到底,注意,先序访问时visit应该在该循环中        pop(s, p); //弹出最后的空指针        if (!stackempty(s))        {            pop(s, p);          //说明两次访问完毕,该指针需要被弹出            push(s, p->rchild); //向右走一步        }    }}

与中序算法不同的地方仅在于:visit函数的位置不同

后序遍历二叉树的栈算法

typedef struct {                     BTNode* ptr;                     enum {0,1,2} mark;                   } PMType; //有mark域的结点指针类型 void PostOrder_Stack(BiTree T)//后序遍历二叉树的非递归算法,用栈{  PMType a;  InitStack(S); //S的元素为PMType类型  Push (S,{T,0}); //根结点入栈  while(!StackEmpty(S))  {    Pop(S,a);    switch(a.mark)    {      case 0:        Push(S,{a.ptr,1}); //修改mark域        if(a.ptr->lchild) Push(S,{a.ptr->lchild,0}); //访问左子树        break;      case 1:        Push(S,{a.ptr,2}); //修改mark域        if(a.ptr->rchild) Push(S,{a.ptr->rchild,0}); //访问右子树        break;      case 2:        visit(a.ptr); //访问结点,返回        //未push仅pop,所以会减少stacksize    }  }//while}//PostOrder_Stack

这个代码我确实想不出来,以上为参考答案,通过switch判断mark标志域,在以左孩子访问时,记标志为1,再次访问到1时说明应该访问右孩子。在开始访问右孩子时,记标志为2,再次访问到2时意味着对该结点的访问已经结束,应该visit。

Ⅱ由后序中序序列求先序层序的递归算法


题目:

7-2 树的遍历 

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

72 3 1 5 7 6 41 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

解题思路:

采用递归的思路进行解题,我们很容易观察到该题存在递归结构:

如输入样例,由于后序最后一个输出为根结点,依据这个性质,我们可以将中序再分为左右子树(新的中序:123,后序:231),新的子树又可以找到新的根结点,比较神奇的是,按照先左后右的顺序依次探访,依次保存得到的序列即为先序,为了得到层序,我采用了结构体数组,保存层的信息,有了层的信息,我们可以直接通过排序(可以直接使用STL:sort)就可以得到层序序列。

a2e1da92c218082414a2da0ae751272f.png

代码实现

#include #include using namespace std;typedef struct Node{    int level; //用于保存层的信息    int data;  //用于保存数据    bool operatorconst Node &n)     {        if (this->level < n.level)            return true;        return false;    } //结构体内重载小于运算符,方便sort直接操作} Node;int numat = 0;                                                                                     //指向num数组当前的位置,num数组用于存放结果void Operate(int *in, int inst, int ined, int *post, int postst, int posted, Node *num, int level) //定义操作函数{    //这个函数参数的含义:从中序in列表第inst个到第ined个,后序列表post第postst个到第posted个,存放于num中,此时位于level层    if (inst == ined) //开始与结尾重合,到达递归终点,退出    {        num[numat].data = *(in + inst);        num[numat].level = level;        return;    }                           //直接把该结点放入结果中    int sym = *(post + posted); //读取最后一个后序    int count = 0;              //count的作用是后面方便确定下次递归的起点和终点    int i;    for (i = inst; *(in + i) != sym; i++) //i从起点开始,到标志结束        count++;    num[numat].data = sym;    num[numat].level = level; //将根节点放入    if (i != inst)    {        numat++;        Operate(in, inst, i - 1, post, postst, postst + count - 1, num, level + 1);    } //左边如果有,递归左子树    else if (i == inst && i != ined)    {        numat++;        Operate(in, i + 1, ined, post, postst, posted - 1, num, level + 1);    }                           //左边没有,递归右子树(count为0右子树公式会出现错误)    if (i != inst && i != ined) //两边都有,递归右子树    {        numat++;        Operate(in, i + 1, ined, post, posted - count, posted - 1, num, level + 1);    }}int main(){    int n;    cin >> n;    int in[n];    int post[n];    for (int i = 0; i < n; i++)        cin >> post[i];    for (int i = 0; i < n; i++)        cin >> in[i];    Node num[n];    Operate(in, 0, n - 1, post, 0, n - 1, num, 0); //进行操作    sort(num, num + n);//不进行排序则输出先序    //或者使用冒泡排序    // for (int i = 0; i < n - 1; i++)    //     for (int j = 0; j < n - 1; j++)    //         if (num[j].level > num[j + 1].level)    //         {    //             Node tmp = num[j];    //             num[j] = num[j + 1];    //             num[j + 1] = tmp;    //         }    for (int i = 0; i < n - 1; i++)        cout << num[i].data << ' ';    cout << num[n - 1].data; //输出结果}

该程序存在的一个小瑕疵:

6组测试数据,最后一组报段错误,始终找不出......

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值