从键盘输入先序序列,创建二叉树,然后对T进行非递归中序遍历、递归后序遍历和层序遍历

数据结构之二叉树操作

算法思想
1、创建二叉树:使用递归的方法。从键盘输入一个字符,判断其是否为空字符,本代码用’#'代替空字符。如果是,则该节点赋值NULL;如果不是,则该节点的数据域data赋值为该字符,同时调用函数自身,传入左孩子指针,继续调用函数自身,传入右孩子指针。
流程图:
算法一流程图

2、非递归中序遍历方法1:先将根节点压入栈中。当栈非空时,当获取栈顶元素的栈顶元素不为空时,将栈顶元素的左节点压入栈中;继续判断栈非空,弹出栈顶元素,输出元素的数据域,再将元素的右节点压入栈中。
流程图:算法2 流程图

3、递归后序遍历:判断节点非空,如果空则返回0,如果非空则调用函数自身,传入左指针,继续调用,传入右指针;最后打印该节点的数据域。
流程图:
算法3

4、层序遍历:先将根节点加入队列。当队列非空,执行出队操作,同时打印出队元素的数据域;如果该元素的左节点非空,则加入队列,如果右节点非空,则也加入队列,循环操作,直至队列为空。
流程图:
算法4
流程图仅供参考

#include<stdlib.h>
#include<stdio.h>
#define MAXQSIZE 50
#define STACK_INIT_SIZE 50
#define TRUE 1               /*状态码预定义*/
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;
typedef char TElemType;
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild,*rchild;  //左右孩子指针
}BiTNode, *BiTree; 
typedef struct BiTNode* QElemtype;
typedef  struct BiTNode* SElemtype; 

typedef struct
{
    QElemtype *base;
    int front,rear;
}SqQueue;

typedef struct 
{
    SElemtype base[STACK_INIT_SIZE];
    int  top;
    int stacksize;
}SqStack;

Status InitStack(SqStack *S)     
{
    S->top=0;
    S->stacksize = STACK_INIT_SIZE;
    return OK;
}

SElemtype GetTop(SqStack S)   
{
    if(S.top==0)   
        return ERROR;
    else
        return S.base[S.top-1];
}

Status Push(SqStack *S,SElemtype e)   
{
    S->base[S->top++]=e;
    return OK;
}

SElemtype Pop(SqStack *S)   
{
    if(S->top == 0) return ERROR;
    S->top--;
    return S->base[S->top];
    
}

Status StackEmpty(SqStack S)  
{
    return S.top==0;
}

int GetStackSize(SqStack S)  
{
    return S.top-1;
}

Status InitQueue(SqQueue *Q)   
{
    Q->base=(QElemtype*)malloc(sizeof(QElemtype));
    if(!Q->base) exit(OVERFLOW);
    Q->front=Q->rear=0;
    return OK;
}

Status EnQueue(SqQueue *Q,QElemtype e)   
{
    if((Q->rear+1)%MAXQSIZE==Q->front)     /*If the queue is full*/
    {
        printf("The queue is full!\n");    
        return ERROR;   
    }
    Q->base[Q->rear]=e;      
    Q->rear=(Q->rear+1)%MAXQSIZE;
    return OK;
}

Status Dequeue(SqQueue *Q,QElemtype *e)   
{
    if(Q->front==Q->rear) 
    {
        printf("The queue is empty!\n");
        return ERROR;
    }
    *e=Q->base[Q->front];
    Q->front=(Q->front+1)%MAXQSIZE;
    return OK;
}

Status TraverseQueue(SqQueue Q)   
{
    int i;
    i=Q.front;
    printf("The elements in the queue are:");
    while((i%MAXQSIZE)!=Q.rear)
    {
        printf("%d ",Q.base[i]);
        i++;
    }
    printf("\n");
    return OK;
}

Status QueueEmpty(SqQueue q)   
{
    return q.rear==q.front;
}

Status CreateBiTree_1(BiTree *T,char ch[])   //先序遍历创建节点,递归(自动输入)
{
    static int i=-1;  //静态变量
    i++;      
    if(ch[i]=='#') 
        *T=NULL;
    else if(ch[i]!='\0')
    {
        *T=(BiTNode *)malloc(sizeof(BiTNode));  //为T分配内存空间
        if(T==NULL) exit(OVERFLOW);
        (*T)->data=ch[i];
        CreateBiTree_1(&(*T)->lchild,ch);     
        CreateBiTree_1(&(*T)->rchild,ch);      
    }
    return OK;
}

Status CreateBiTree_2(BiTree *T)   //先序遍历创建节点,递归(手动输入)
{
    char e;
    scanf("%c",&e);  
    if(e=='#') 
        *T=NULL;
    else 
    {
        *T=(BiTNode *)malloc(sizeof(BiTNode));  //为T分配内存空间
        if(T==NULL) exit(OVERFLOW);
        (*T)->data=e;
        CreateBiTree_2(&(*T)->lchild);     
        CreateBiTree_2(&(*T)->rchild);      
    }
    return OK;
}

Status PrintElement(TElemType e)   //简单的打印元素函数
{
    printf("%c",e);
    return OK;
}

/*先序遍历,使用递归*/
void PreOrderTraverse(BiTree T,Status (*visit)(TElemType e))  
{
    if(T==NULL)   return;
    visit(T->data);
    PreOrderTraverse(T->lchild,visit);
    PreOrderTraverse(T->rchild,visit); 
}

/*非递归中序遍历方法1*/
Status InOrderTraverse_1(BiTree T,Status (*visit)(TElemType e))
{
    SqStack S;
    BiTree p;
    InitStack(&S);  //初始化栈
    Push(&S,T);
    while(!StackEmpty(S))  //栈非空
    {
        while(p=GetTop(S)) Push(&S,p->lchild);
        p=Pop(&S);
        if(!StackEmpty(S))
        {
            p=Pop(&S); if(!visit(p->data)) return ERROR;
            Push(&S,p->rchild);
        }
    }
}

/*非递归中序遍历方法2*/
Status InOrderTraverse_2(BiTree T,Status(*visit)(TElemType e))
{
    SqStack S;
    BiTree p;
    InitStack(&S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            Push(&S,p);
            p=p->lchild;
        } //左子树全部进栈
        else
        {
            p=Pop(&S);
            if(!visit(p->data)) return ERROR;
            p=p->rchild;
        }
    }
    return OK;
}

/*递归后序遍历*/
Status PostOrderTraverse(BiTree T,Status(*visit)(TElemType e))
{
    if(T==NULL)
    return ERROR;
    PostOrderTraverse(T->lchild,visit);  /*先左后右*/
    PostOrderTraverse(T->rchild,visit);
    visit(T->data);
}

/*层序遍历*/
Status LevelOrderTraverse(BiTree T,Status(*visit)(TElemType e))
{   
    SqQueue q;
    BiTree p;
    InitQueue(&q);   //初始化队列
    EnQueue(&q,T);
    while (!QueueEmpty(q))
    {
        Dequeue(&q,&p);
        printf("%c",p->data);
        if(p->lchild)
            EnQueue(&q,p->lchild);
        if(p->rchild)
            EnQueue(&q,p->rchild);
    }
    return OK;
}

void main()
{
    BiTree T;
    char ch[]="ABC##DE#G##F###"; //测试数据  先序序列
    /*可替换为:"-+a##*b##-c##d##/e##f##"  ,  '#'代表空*/  
    CreateBiTree_1(&T,ch);  //二选一
    //CreateBiTree_2(&T);   //此为符合实验要求函数
    printf("层序遍历:\n");
    LevelOrderTraverse(T,PrintElement);  
    printf("\n后序遍历:\n");
    PostOrderTraverse(T,PrintElement); 
    printf("\n先序遍历:\n");
    PreOrderTraverse(T,PrintElement); 
    printf("\n非递归中序遍历方法1:\n");
    InOrderTraverse_1(T,PrintElement);
    printf("\n非递归中序遍历方法2:\n");
    InOrderTraverse_2(T,PrintElement); 
}
/***狗头保佑
 *               ii.                                         ;9ABH,          
 *              SA391,                                    .r9GG35&G          
 *              &#ii13Gh;                               i3X31i;:,rB1         
 *              iMs,:,i5895,                         .5G91:,:;:s1:8A         
 *               33::::,,;5G5,                     ,58Si,,:::,sHX;iH1        
 *                Sr.,:;rs13BBX35hh11511h5Shhh5S3GAXS:.,,::,,1AG3i,GG        
 *                .G51S511sr;;iiiishS8G89Shsrrsh59S;.,,,,,..5A85Si,h8        
 *               :SB9s:,............................,,,.,,,SASh53h,1G.       
 *            .r18S;..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....,,.1H315199,rX,       
 *          ;S89s,..,,,,,,,,,,,,,,,,,,,,,,,....,,.......,,,;r1ShS8,;Xi       
 *        i55s:.........,,,,,,,,,,,,,,,,.,,,......,.....,,....r9&5.:X1       
 *       59;.....,.     .,,,,,,,,,,,...        .............,..:1;.:&s       
 *      s8,..;53S5S3s.   .,,,,,,,.,..      i15S5h1:.........,,,..,,:99       
 *      93.:39s:rSGB@A;  ..,,,,.....    .SG3hhh9G&BGi..,,,,,,,,,,,,.,83      
 *      G5.G8  9#@@@@@X. .,,,,,,.....  iA9,.S&B###@@Mr...,,,,,,,,..,.;Xh     
 *      Gs.X8 S@@@@@@@B:..,,,,,,,,,,. rA1 ,A@@@@@@@@@H:........,,,,,,.iX:    
 *     ;9. ,8A#@@@@@@#5,.,,,,,,,,,... 9A. 8@@@@@@@@@@M;    ....,,,,,,,,S8    
 *     X3    iS8XAHH8s.,,,,,,,,,,...,..58hH@@@@@@@@@Hs       ...,,,,,,,:Gs   
 *    r8,        ,,,...,,,,,,,,,,.....  ,h8XABMMHX3r.          .,,,,,,,.rX:  
 *   :9, .    .:,..,:;;;::,.,,,,,..          .,,.               ..,,,,,,.59  
 *  .Si      ,:.i8HBMMMMMB&5,....                    .            .,,,,,.sMr
 *  SS       :: h@@@@@@@@@@#; .                     ...  .         ..,,,,iM5
 *  91  .    ;:.,1&@@@@@@MXs.                            .          .,,:,:&S
 *  hS ....  .:;,,,i3MMS1;..,..... .  .     ...                     ..,:,.99
 *  ,8; ..... .,:,..,8Ms:;,,,...                                     .,::.83
 *   s&: ....  .sS553B@@HX3s;,.    .,;13h.                            .:::&1
 *    SXr  .  ...;s3G99XA&X88Shss11155hi.                             ,;:h&,
 *     iH8:  . ..   ,;iiii;,::,,,,,.                                 .;irHA  
 *      ,8X5;   .     .......                                       ,;iihS8Gi
 *         1831,                                                 .,;irrrrrs&@
 *           ;5A8r.                                            .:;iiiiirrss1H
 *             :X@H3s.......                                .,:;iii;iiiiirsrh
 *              r#h:;,...,,.. .,,:;;;;;:::,...              .:;;;;;;iiiirrss1
 *             ,M8 ..,....,.....,,::::::,,...         .     .,;;;iiiiiirss11h
 *             8B;.,,,,,,,.,.....          .           ..   .:;;;;iirrsss111h
 *            i@5,:::,,,,,,,,.... .                   . .:::;;;;;irrrss111111
 *            9Bi,:,,,,......                        ..r91;;;;;iirrsss1ss1111
 */
  • 50
    点赞
  • 103
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
### 回答1: 首先,我们需要了解一下二叉树的基本概念。二叉树是一种树形结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的遍历方式有三种:前序遍历、中序遍历后序遍历。 1、从键盘输入先序序列创建对应二叉树t 我们可以通过递归的方式来创建二叉树。具体步骤如下: 1)从键盘输入一个字符,如果该字符为#,则表示该节点为空,返回NULL;否则,创建一个新节点,并将该字符存储在节点中。 2)递归创建左子树,将返回的节点作为当前节点的左子节点。 3)递归创建右子树,将返回的节点作为当前节点的右子节点。 4)返回当前节点。 代码如下: ``` #include <stdio.h> #include <stdlib.h> typedef struct TreeNode { char data; struct TreeNode *left; struct TreeNode *right; } TreeNode; TreeNode* createTree() { char c; scanf("%c", &c); if (c == '#') { return NULL; } TreeNode *root = (TreeNode*)malloc(sizeof(TreeNode)); root->data = c; root->left = createTree(); root->right = createTree(); return root; } ``` 2、对t进行非递归中序遍历 非递归中序遍历需要借助栈来实现。具体步骤如下: 1)从根节点开始,将其所有左子节点依次入栈。 2)弹出栈顶节点,访问该节点。 3)如果该节点存在右子节点,则将其右子节点入栈。 4)重复步骤2和3,直到栈为空。 代码如下: ``` void inorderTraversal(TreeNode *root) { if (root == NULL) { return; } TreeNode *stack[100]; int top = -1; TreeNode *p = root; while (p != NULL || top != -1) { while (p != NULL) { stack[++top] = p; p = p->left; } if (top != -1) { p = stack[top--]; printf("%c ", p->data); p = p->right; } } } ``` 3、递归后序遍历 递归后序遍历的顺序是先访问左子树,再访问右子树,最后访问根节点。代码如下: ``` void postorderTraversal(TreeNode *root) { if (root == NULL) { return; } postorderTraversal(root->left); postorderTraversal(root->right); printf("%c ", root->data); } ``` 4、层序遍历 层序遍历需要借助队列来实现。具体步骤如下: 1)将根节点入队。 2)从队列中取出一个节点,访问该节点。 3)将该节点的左子节点和右子节点依次入队。 4)重复步骤2和3,直到队列为空。 代码如下: ``` void levelTraversal(TreeNode *root) { if (root == NULL) { return; } TreeNode *queue[100]; int front = , rear = ; queue[rear++] = root; while (front != rear) { TreeNode *p = queue[front++]; printf("%c ", p->data); if (p->left != NULL) { queue[rear++] = p->left; } if (p->right != NULL) { queue[rear++] = p->right; } } } ``` 完整代码如下: ``` #include <stdio.h> #include <stdlib.h> typedef struct TreeNode { char data; struct TreeNode *left; struct TreeNode *right; } TreeNode; TreeNode* createTree() { char c; scanf("%c", &c); if (c == '#') { return NULL; } TreeNode *root = (TreeNode*)malloc(sizeof(TreeNode)); root->data = c; root->left = createTree(); root->right = createTree(); return root; } void inorderTraversal(TreeNode *root) { if (root == NULL) { return; } TreeNode *stack[100]; int top = -1; TreeNode *p = root; while (p != NULL || top != -1) { while (p != NULL) { stack[++top] = p; p = p->left; } if (top != -1) { p = stack[top--]; printf("%c ", p->data); p = p->right; } } } void postorderTraversal(TreeNode *root) { if (root == NULL) { return; } postorderTraversal(root->left); postorderTraversal(root->right); printf("%c ", root->data); } void levelTraversal(TreeNode *root) { if (root == NULL) { return; } TreeNode *queue[100]; int front = , rear = ; queue[rear++] = root; while (front != rear) { TreeNode *p = queue[front++]; printf("%c ", p->data); if (p->left != NULL) { queue[rear++] = p->left; } if (p->right != NULL) { queue[rear++] = p->right; } } } int main() { TreeNode *root = createTree(); printf("非递归中序遍历:"); inorderTraversal(root); printf("\n"); printf("递归后序遍历:"); postorderTraversal(root); printf("\n"); printf("层序遍历:"); levelTraversal(root); printf("\n"); return ; } ``` ### 回答2: 运行时从键盘输入先序序列创建对应二叉树t,可以使用递归方法,也可以使用非递归方法。 先以递归方法为例,实现创建二叉树的过程: 1. 从输入读取先序序列,如果输入字符为“#”,说明该节点为空,返回NULL。 2. 否则,新建一个节点,将输入字符存储在该节点中,然后递归调用创建左子树,再递归调用创建右子树。 3. 返回新建的节点。 代码实现如下: ``` #include<iostream> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode* createTree() { char ch; cin >> ch; if (ch == '#') return NULL; TreeNode* root = new TreeNode(ch - '0'); root->left = createTree(); root->right = createTree(); return root; } ``` 然后,针对创建好的二叉树t,实现非递归中序遍历递归后序遍历层序遍历。 首先,非递归中序遍历采用栈来辅助实现,遍历过程如下: 1. 从根节点开始,将节点压入栈中。 2. 循环执行以下操作:如果当前节点不为空,将其左子树节点压入栈中,否则弹出栈顶元素并输出,并将当前节点切换为栈顶元素的右子树节点。 3. 当栈为空时,遍历结束。 代码实现如下: ``` void inorderTraversal(TreeNode* root) { stack<TreeNode*> stk; while (!stk.empty() || root != NULL) { if (root != NULL) { stk.push(root); root = root->left; } else { root = stk.top(); stk.pop(); cout << root->val << " "; root = root->right; } } cout << endl; } ``` 其次,递归后序遍历的过程较为简单,代码实现如下: ``` void postorderTraversal(TreeNode* root) { if (root == NULL) return; postorderTraversal(root->left); postorderTraversal(root->right); cout << root->val << " "; return; } ``` 最后,层序遍历采用队列来辅助实现,遍历过程如下: 1. 从根节点开始,将节点加入队列中。 2. 循环执行以下操作,直到队列为空:弹出队首元素,将节点值输出,然后将其左、右子节点加入队列。 代码实现如下: ``` void levelOrderTraversal(TreeNode* root) { queue<TreeNode*> q; if (root) q.push(root); while (!q.empty()) { TreeNode* cur = q.front(); q.pop(); cout << cur->val << " "; if (cur->left) q.push(cur->left); if (cur->right) q.push(cur->right); } cout << endl; } ``` 这样,就实现了对创建好的二叉树t的非递归中序遍历递归后序遍历层序遍历。 ### 回答3: 题目要求实现对二叉树非递归中序遍历递归后序遍历层序遍历,而二叉树的建立需要先根据先序序列构建出对应的二叉树t,因此进入问题的对下一步操作将是基于已经成功构建的二叉树t来实现的。 1、根据先序序列构建二叉树 先序遍历的顺序是:根节点-左子树-右子树。因此,我们可以首先读取根节点的值,然后判断是否为叶子节点。如果不是,则继续读取下一个值作为根节点的左子节点,并同样递归构建左子树。如果左子树构建完成,则根据刚才的方法递归右子树。最终构建完成整个二叉树。 2、非递归中序遍历 中序遍历的顺序是:左子树-根节点-右子树。我们可以采用栈这种数据结构来实现非递归中序遍历,具体实现方法如下: - 将根节点加入栈中,并将其左子树遍历的左儿子加入栈中(整个根节点的左子树都会被依次压入栈中) - 依次弹出栈中的元素,输出其值。若该节点存在右子树,则将其右子节点压入栈中。 因为左子树的所有元素都会先被压入栈中,因此弹出的顺序就是中序遍历的顺序。 3、递归后序遍历 后序遍历的顺序是:左子树-右子树-根节点。在递归后序遍历时,我们可以先对左子树进行递归,再对右子树进行递归,最后再输出根节点。因此,递归函数应当具有如下形式: void PostorderTraversal(TreeNode* root){ if(!root) return; PostorderTraversal(root -> left); PostorderTraversal(root -> right); cout << root -> val << " "; } 其中,root即为当前节点。 4、层序遍历 层序遍历的顺序是:按照层次依次输出节点的值。我们可以使用队列这种数据结构来实现层序遍历,具体实现方法如下: - 将根节点加入队列中 - 依次读取队列中的元素,输出其值,并将其左子树和右子树加入队尾。 由于队列的先进先出特点,因此元素的访问顺序就是按照层次逐一访问的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

m0_46560176

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

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

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

打赏作者

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

抵扣说明:

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

余额充值