数据结构应用题第五章树代码c

本文介绍了二叉树的自下而上、自右而左的层次遍历算法,同时提供了非递归求解孩子兄弟表示法森林叶子结点数的方法,通过链式数据结构实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 试给出二叉树的自下而上,自右而左的层次遍历算法
    思路:按照层次遍历的思想正常遍历,但是多使用一个栈来存储层次遍历中出队列的元素,层次遍历结束后把栈中元素全部出栈,出栈的顺序就是题目要求的层次遍历算法。还有一种思路,用一个链表存储层次遍历的结果,然后对链表进行倒置。两种思路都可以。

树定义

#ifndef TREE_H
#define TREE_H

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>


// 二叉树的顺序存储结构,适合于完全二叉树和满二叉树
#define MaxSize 100
typedef int ElemType;
typedef char DataType;
typedef struct TreeNode{
    ElemType value;//结点中的数据元素
    bool isEmpty;//结点是否为空
}TreeNode;
// TreeNode t[MaxSize] //初始化长度为MaxSize的数组t
// for(int i=0;i<MaxSize;i++){
//     t[i].isEmpty=true;//初始化标记为空
// }


// 二叉树的链式存储
typedef struct BiTNode{
    DataType data;
    struct BiTNode *lchild,*rchild;
    // struct BiTNode *parent;//用来方便存储父节点指针,这也是所谓的三叉链表
}BiTNode,*BiTree;

void createTree(BiTree *T);//先序创建一棵树 ABD##E##CF##G##
#endif

栈定义和实现

#ifndef LISTACK_H
#define LISTACK_H
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include "tree.h"
// 链栈,不带头结点的情况
typedef BiTree TreeType;//入栈的节点是一棵树,不是树的一个节点,否则树会断层
typedef struct LinkNode{
    TreeType data;//数据域
    struct LinkNode *next;
}LinkNode,*LinkStack;

bool InitStack4(LinkStack *s);//初始化不带头结点的栈
bool Push4(LinkStack *s,TreeType x);//入栈
bool Pop4(LinkStack *s,TreeType *x);//出栈
void printfStack4(LinkStack s);//打印
bool EmptyStack4(LinkStack s);//空栈
bool GetTop(LinkStack s,TreeType *x);
#endif
#include "listack.h"


bool InitStack4(LinkStack *s){
    *s=NULL;//栈空,不带头结点
    return true;
}
bool EmptyStack4(LinkStack s){
    if(s==NULL){
        return true;
    }
    return false;
}
// x在这里表示的是一棵树
bool Push4(LinkStack *s,TreeType x){
    LinkNode *p=(LinkNode *)malloc(sizeof(LinkNode));
    if(p==NULL)
        return false;
    p->data=x;
    // 这一步很容易错
    p->next=(*s);
    (*s)=p;
    return true;
}
bool Pop4(LinkStack *s,TreeType *x){
    // printf("Pop-%d",x);
    if((*s)==NULL)//空表
        return false;
    LinkNode *p=*s;
    *s=(*s)->next;
    *x=p->data;
    free(p);

    return true;
}
bool GetTop(LinkStack s,TreeType *x){
   if(s==NULL)
        return false;
    *x=s->data;
    return true;
}
void printfStack4(LinkStack s){
    // s=NULL;
    LinkNode *p=s;
    while(p!=NULL){
        printf("%c->",p->data->data);
        p=p->next;
    }
    printf("\n");
}

队列定义和实现

#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include "listack.h"

// typedef int ElemType;
typedef struct LinkNode2{//链式队列结点
    TreeType data; 
    struct LinkNode2 *next;
}LQNode;
typedef struct{//链式队列
    LQNode *front,*rear;
}LQueue;
// 带头结点的初始化
void InitLQueue_withHead(LQueue *Q);
// 队列为空
bool LQueueEmpty_withHead(LQueue Q);
// 入队
void EnLQueue_withHead(LQueue *Q,TreeType x);
// 出队
bool DeLQueue_withHead(LQueue *Q,TreeType *x);
void printfLQueue_withHead(LQueue Q);
#endif

#include "linkqueue.h"

// 带头结点的初始化
void InitLQueue_withHead(LQueue *Q){
    (*Q).front=(LQNode *)malloc(sizeof(LQNode));
    (*Q).rear=(*Q).front;
    (*Q).front->next=NULL;
}
bool LQueueEmpty_withHead(LQueue Q){
    if(Q.front==Q.rear)
        return true;
    return false;
}
// 入队
void EnLQueue_withHead(LQueue *Q,TreeType x){
    LQNode *s=(LQNode *)malloc(sizeof(LQNode));
    s->data=x;
    s->next=NULL;
    (*Q).rear->next=s;
    (*Q).rear=s;//修改表尾指针
}
// 出队
bool DeLQueue_withHead(LQueue *Q,TreeType *x){
    if((*Q).front==(*Q).rear)//空队
        return false;

    LQNode *p=(*Q).front->next;
    *x=p->data;
    (*Q).front->next=p->next;
    if((*Q).rear==p)//最后一个结点出队
        (*Q).rear=(*Q).front;
    free(p);
    return true;
}
void printfLQueue_withHead(LQueue Q){
    if(Q.front==Q.rear)
        return;

    LQNode *p=Q.front->next;
    while(p!=NULL){
        printf("%d<-",p->data);
        p=p->next;
    }
    printf("\n");
}

倒置层次遍历实现

#include "tree.h"
#include "listack.h"
#include "linkqueue.h"
// create——ABD##E##CF##G##
void createTree(BiTree *T){
    DataType ch;
    scanf("%c",&ch);
    // while(getchar()!='\n');//当获取一个有效字符时结束循环
    if(ch=='#'){
        *T=NULL;
        return;
    }
    else{
        *T=(BiTNode *)malloc(sizeof(BiTNode));
        (*T)->data=ch;
        createTree(&((*T)->lchild));
        createTree(&((*T)->rchild));
    }
}
void level(BiTree T){
    // 创建并初始化一个栈
    LinkStack L;
    InitStack4(&L);

    // 创建并初始化一个队列
    LQueue Q;
    InitLQueue_withHead(&Q);
    BiTNode* temp=NULL;//用来存储出队列的元素
    //层次遍历
    EnLQueue_withHead(&Q,T);
    Push4(&L,T);
    while(!LQueueEmpty_withHead(Q)){//如果队列不为空
        DeLQueue_withHead(&Q,&temp);
        if(temp->lchild!=NULL){
            EnLQueue_withHead(&Q,temp->lchild);
            Push4(&L,temp->lchild);
        }
        if(temp->rchild!=NULL){
            EnLQueue_withHead(&Q,temp->rchild);
            Push4(&L,temp->rchild);
        }
    }
    // while()
    printfStack4(L);
}
void test4(){
    BiTree T;
    printf("请连续输入字符,中间不要有空格和换行。。。\n");
    createTree(&T);
    level(T);
}

实现截图
在这里插入图片描述

  • 假设二叉树采用二叉链表的存储结构,设计一个非递归算法求二叉树的高度
    思路和二叉树的先序遍历的非递归实现一样。只是这里把输出改为对高度的的++和- -。
// 利用栈来实现先序遍历的非递归算法
int PreOrder(BiTree T){
    LinkStack S;
    InitStack4(&S);

    BiTNode *p=T;
    int length=0;//高度
    int temp=0;//临时变量
    while(p!=NULL||!EmptyStack4(S)){
        if(p!=NULL){
            // printf("%c",p->data);
            temp++;
            Push4(&S,p);
            p=p->lchild;
        }else{//说明左子树已经遍历完成
            Pop4(&S,&p);
            length=length>=temp?length:temp;
            temp--;//这里把结点出栈,所以这里的temp要--
            p=p->rchild;
        }
    }
    return length;
    printf("\n");
}
  • 编程求以孩子兄弟表示法存储的森林的叶子结点数
    思路:首先用孩子兄弟表示法存储的森林是以二叉树的存储方式保存的,其左子树代表当前结点的第一个孩子结点,右子树代表当前结点的右兄弟,如果右兄弟还有右兄弟(同一层),那么其右兄弟的右兄弟存储在右兄弟的右子树上,以此类推。以此为思路,当左孩子为空说明是叶子节点,把叶子节点的数量 1 加上右兄弟的数量,就是森林的叶子结点的数量。实现如下:
#ifndef TREEPLUS_H
#define TREEPLUS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef char ElemType;
// 孩子兄弟表示法(链式存储)——树和二叉树相互转化的问题
typedef struct CSNode{
    ElemType data;
    struct CSNode *firstchild,*nextsibling;//第一个孩子和右兄弟指针
}CSNode,*CSTree;

void createTreeplus(CSTree *T);//创建一棵树
#endif
#include "treeplus.h"

// create——ABD##E##CF##G##
void createTreeplus(CSTree *T){
    ElemType ch;
    scanf("%c",&ch);
    // while(getchar()!='\n');//当获取一个有效字符时结束循环
    if(ch=='#'){
        *T=NULL;
        return;
    }
    else{
        *T=(CSNode *)malloc(sizeof(CSNode));
        (*T)->data=ch;
        createTreeplus(&((*T)->firstchild));
        createTreeplus(&((*T)->nextsibling));
    }
}
#include "treeplus.h"

int leaves_num(CSTree T){
    if(T==NULL)
        return 0;
    if(T->firstchild==NULL)//表示一定是叶子节点
        return 1+leaves_num(T->nextsibling);//返回叶子结点数目以及它兄弟的数量
    else
        return leaves_num(T->firstchild)+leaves_num(T->nextsibling);//返回孩子子树和兄弟子树叶子数之和
}

int test5_167(){
    CSTree T;
    createTreeplus(&T);
    printf("%d\n",leaves_num(T));
}

void main(){
    printf("请输入一棵树。。。\n");
    test5_167();
}
  • 以孩子兄弟链表为存储结构,请设计递归算法求树的深度
    思路:和二叉树求树高差不多
#include "treeplus.h"
// create——ABD##E###

int height(CSTree T){
    if(T==NULL)
        return 0;
    int hc=0,hs=0;
    hc=height(T->firstchild)+1;//第一个子女的树高,所以后面要加1
    hs=height(T->nextsibling);//兄弟结点的树高,同一层,所以不用+1
    if(hc>hs)
        return hc;
    else
        return hs;
}
void test6_167(){
    CSTree T;
    createTreeplus(&T);
    printf("%d\n",height(T));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值