给定二叉树的先序遍历有多少种可能的二叉树


title: 给定二叉树的先序遍历有多少种可能的二叉树
date: 2023-05-16 11:42:26
tags: 数据结构与算法


  • 给定二叉树的先序遍历有多少种可能的二叉树

    **问题:**给定二叉树的先序遍历有多少种可能的二叉树
    git地址:https://github.com/944613709/HIT-Data-Structures-and-Algorithms

    算法思想:

    在二叉树先序遍历非递归算法中,二叉树先序遍历序列即为二叉树结点入栈顺序,而二叉树中序遍历序列即为二叉树结点出栈顺序,已知二叉树的先序遍历序列和中序遍历序列,即可确定一棵二叉树,所以问题等价于已知二叉树结点入栈顺序,有多少种可能的出栈顺序。

    用队列来模拟输入,队列的输出则按照原先序列的顺序。再使用一个栈来模拟入栈和出栈,结果保存在另外一个队列

    对于任意的一个元素k,要么进栈处理下一个元素,要么判断栈是否为空若不为空则进行出栈继续处理元素。当所有的元素都入栈了,k=n+1时候就可以输出队列和栈的元素,成为一个出栈序列,计数加一,再执行回溯,递归

    算法步骤:

    \1. 初始化栈和队列

    \2. 调用OutPut_S(1);函数执行从k=1开始

    (1) 如果k!=n+1,需要后续继续递归

    ① 将当前元素k入栈

    ② 处理下一个元素k+1调用OutPut_S(k+1);

    ③ 进行回溯到之前元素的状态利用pop(s)

    ④ 判断栈是非为空,如果空

    \1) 栈顶元素出栈

    \2) 存入队列

    \3) 再次调用OutPut_S(k);处理当前元素k

    \4) 出队

    \5) 将此时的元素入栈,进行回溯操作,也就是抹去之前的处理,进行递归处理其他元素

    (2) 如果k==n+1时,完成递归,所有元素都已经入过栈完毕,作为出口

    ① 打印队列元素

    \1) While直到p->next!=NULL

    a. 每一次printf并且p=p->next;

    ② 打印栈元素

    \1) 利用for循环将所有元素printf

    ③ 并且计数利用cout++

    测试样例

    img

    imgimg

    具体代码

  `\#include <stdio.h>`

  `\#include <stdlib.h>`

  `\#include <string.h>`

  `\#include <stdbool.h>`

  `\#define MAX 99`

  `` 

  `typedef struct STACK`

  `{`

    `int top;`

    `int data[MAX];`

  `}STACK;`

  `void push(STACK *s,int data)`

  `{`

    `s->data[++s->top]=data;`

  `}`

  `void pop(STACK *s)`

  `{`

    `s->top--;`

  `}`

  `void STACK_Initial(STACK *s)`

  `{`    

    `s->top=-1;`

  `}`

  `` 

  `int top(STACK *s)`

  `{`

    `return s->data[s->top];`

  `}`

  `bool Isempty(STACK *s)`

  `{`

    `if(s->top==-1)`

  ​    `return true;`

    `else`

  ​    `return false;`

  `}`

  `typedef struct Qnode`

  `{`

    `int data;`

    `struct Qnode* next;`

  `}Qnode;`

  `` 

  `typedef struct Queue`

  `{`

    `Qnode* front;`

    `Qnode* rear;`

  `}queue;`

  `void Q_Initial(queue *q)`

  `{`

    `Qnode *p=malloc(sizeof(Qnode));`

    `p->next=NULL;`

    `q->front=p;`

    `q->rear=p;`

  `}`

  `void enqueue(queue *q,int k)`

  `{`

    `Qnode *p=malloc(sizeof(Qnode));`

    `p->data=k;`

    `p->next=NULL;`

    `q->rear->next=p;`

    `q->rear=p;`

  `}`

  `void dequeue(queue *q)`

  `{`

    `Qnode *p=q->front->next;`

    `q->front->next=p->next;`

    `free(p);`

    `if(q->front->next==NULL)`

  ​    `q->rear=q->front;`

  `}`

  `queue *q; //队列保存已出栈元素`

  `int n;`

  `int count=0;`

  `STACK *s;`

  `` 

  `void OutPut_S(int k)`

  `{`

    `int temp;`

    `if(k!=n+1)//当k!=n+1时候继续递归` 

    `{`

  ​    `push(s,k);` 

  ​          `//当前元素k入栈`

  ​    `OutPut_S(k+1);` 

  ​          `//处理下一元素k+1`

  ​    `pop(s);  //回溯至当前元素状态`

  ​    `if(!Isempty(s)) //当栈非空时`

  ​    `{`

  ​      `temp=top(s);`

  ​      `pop(s);`

  ​      `enqueue(q,temp);` 

  ​      `OutPut_S(k);`

  ​      `dequeue(q);`

  ​      `push(s,temp);`

  ​    `}`

    `}`

    `else if(k==n+1)` 

    `{//当k==n+1时候结束递归` 

  ​    `Qnode* p=q->front;`

  ​    `while(p->next!=NULL)`

  ​    `{    //将队列元素打印——已经出栈的元素` 

  ​      `printf("%d ",p->next->data);` 

  ​      `p=p->next;`

  ​    `}`

  ​    `int j;`

  ​    `//然后再打印栈的元素 ,然后回溯` 

  ​    `for(j=s->top;j>=0;j--)`

  ​      `printf("%d ",s->data[j]);` 

  ​    `count++; //计数共有几种可能`

  ​    `printf("\n");`

  ​    `return ;`

    `}`

  ``  

  `}`

  `` 

  `int main()`

  `{`

    `s = malloc(sizeof(STACK));`

    `STACK_Initial(s);`

    `q = malloc(sizeof(queue));`

    `Q_Initial(q);`

    `printf("请输入先序序列有多少个元素\n");`

  ​    `scanf("%d",&n);`

    `OutPut_S(1);`

    `printf("共有%d种可能",count);`

    `return 0;`

  `}`

  `` 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对称二叉树是从根节点开始,访问根节点,然后按照左后右的顺递归遍左子树和右子树。这里引用的方法有三种思路实现,其中思路1是最基本的实现方式,通过递归的方式遍两次树来判断是否对称。思路1的方法会导致整体上遍了这棵树两次,但实际上只需要比较到两个遍节点相遇时即可停止,因为后续的比较结果和前面是完全一致的。所以,对于给定的对称二叉树只需要比较到两个遍节点相遇时即可停止。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [leetcode:Leetcode的解决方案,用JAVA编写](https://download.csdn.net/download/weixin_42121412/19697315)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [[树] 101. 对称二叉树(前 + 方法优化)](https://blog.csdn.net/m0_38142029/article/details/108089313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fars

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值