二叉树递归实现:统计二叉树结点数、统计叶子节点数、换左右子树、复制二叉树;二叉排序树建立并实现查找;顺序表:学生成绩录入并按成绩排序

该博客介绍了普通二叉树、二叉排序树和顺序表的相关功能实现。包括.c文件接口函数调用与菜单面板初始化,.h文件对各类函数的定义,如递归建立二叉树、复制树、计算结点个数等,还给出了各功能的代码及运行结果,文末提供完整代码。

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

因为嫌麻烦不想分开写所以把三个部分写在了一起,本例程内容包括普通二叉树、二叉排序树和顺序表三部分,在main.c函数中通过调用不同的函数实现;文末有完整代码

 有问题的UU欢迎一起讨论学习

一、.c文件接口函数的调用以及菜单面板的初始化

#include"Module.h"
int main()
{
    int choice;
    BiTree T,NewT;
    printf("输入二叉树元素,以“#”结束T:\n");
    printf("如果是调用功能函数5,功能函数7此时输入'#'退出二叉树数据输入就行\n");
    CreateBiTree(T);
    PreOrderTraverse(T);//遍历原二叉树
    printf("\n");
    while(1)
 {
    printf("-------------------------------------------------<请选择要执行的操作>----------------------------------------------\n");
    printf("**\t1:统计二叉树结点数\t2:统计叶子节点数\t\t3:交换左右子树\t\t\t\t\t**\n");
    printf("**\t4:复制二叉树\t\t5:二叉排序树查找\t\t6:退出\t\t7:学生成绩录入并按成绩排序\t**\n");
    printf("-------------------------------------------------------<菜单>------------------------------------------------------\n");
    scanf("%d",&choice);
    switch(choice)
    {
        case 1:
                printf("树节点数为:%d\n",NodeCount(T));
        break;
        case 2:
                printf("叶子结点数为:%d\n",YECOUNT(T));
        break;
        case 3:
               PreOrderTraverse(T);
               printf("\n");
               exchange(T);
               PreOrderTraverse(T);
        break;
        case 4:
                PreOrderTraverse(T);//遍历原二叉树
                Copy(T,NewT);
                printf("\n");
                PreOrderTraverse(NewT);//遍历新二叉树
                printf("\n");
        break;
        case 5:
                EX5();
        break;
        case 6:
                exit(0);
        break;
        case 7:
        SqList L;
        int N,choice;
        printf("请输入您将录入的学生信息个数:\n");
        scanf("%d",&N);
        InitList(L,N);
        Rank(L);
        break;
        default:
                printf("非法输入,请重新输入!!\n");
        break;
    }
 }
}

 实现case5,case7输入方法举例:输入#退出字符二叉树的输入,再选择功能5或者7,再按输入提示进行输入完成相应的功能就行(原因是case5是二叉排序树其数据类型为int;而case1case2,case3,case4操作对象是最开始建立的普通字符二叉树其数据类型为char,而case7是顺序表存储学生信息不是二叉树),也可以完成输入后进入功能6,因为他们不是同一个树,不共用地址

 

二、.h文件对函数的定义

1:树的存储结构

typedef struct BiTNode
{
    TElemType data;//节点数据域
    struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;

2:递归建立字符二叉树

<1>代码

//递归创建树
void CreateBiTree(BiTree &T)
{
    char ch;
    printf("请输入读入的字符:\n");
    scanf("%c",&ch);
    getchar();
    if(ch=='#')
    {
        T=NULL;//递归结束,建空树
    }
    else//递归创建二叉树
    {
        T=new BiTNode;//生成根节点
        T->data = ch;//根节点数据域置为ch
        T->lchild = NULL; // 初始化左子树为空
        T->rchild = NULL; // 初始化右子树为空
        CreateBiTree(T->lchild);//递归创建左子树
        CreateBiTree(T->rchild);//递归创建右子树

    }
}

 <2>运行结果

3:复制树功能函数

<1>代码

//递归复制树
void Copy(BiTree T,BiTree &NewT)
{
    //复制一棵和T完全相同的树
    if(T==NULL)
    {
        NewT =NULL;
        return;
    }
    else
    {
        NewT = new BiTNode;
        NewT->data=T->data;//复制根节点
        Copy(T->lchild,NewT->lchild);//递归复制左子树
        Copy(T->rchild,NewT->rchild);//递归复制右子树
    }
}

 <2>运行结果

4:递归计算二叉树的结点个数函数

<1>代码

//递归计算二叉树的结点个数
int NodeCount(BiTree T) {
	if (T)
		return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
	else
		return 0;
 
}

 <2>运行结果

5:递归统计叶子节点数函数

<1>代码

//递归统计叶子节点数
int YECOUNT(BiTree T)
{
	if(T==NULL){
         return 0;
    }
    else{
        if( (YECOUNT(T->lchild)==NULL)&&(YECOUNT(T->rchild)==NULL) ){
		    return 1; 
		}
		else return YECOUNT(T->lchild) + YECOUNT(T->rchild);
    }
}

 <2>运行结果

6:交换左右子树函数

<1>代码

//交换左右子树
void exchange(BiTree T){/*交换左右子树核心代码*/
	if(T!=NULL){
		BiTree temp;
		temp=T->lchild;
		T->lchild=T->rchild;
		T->rchild=temp;
		exchange(T->lchild);
		exchange(T->rchild);
	}
}

 <2>运行结果

7:二叉树先序遍历函数

//二叉树先序遍历
void PreOrderTraverse(BiTree T)
{
    if(T == NULL) return;
    printf("%c ",T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

8:二叉排序树插入元素

 <1>代码

// 向二叉排序树中插入元素
int insertBST(BiTree *bst, int x){
    if (*bst == NULL){  // 如果二叉排序树为空
        *bst = (BiTree)malloc(sizeof(BiTNode)); // 新建节点
        (*bst)->data = x;
        (*bst)->lchild = (*bst)->rchild = NULL;
        return 1;
    }
    else if ((*bst)->data == x){  // 如果节点已存在
        return 0;
    }
    else if (x < (*bst)->data){  // 如果节点应该插入到左子树
        return insertBST(&((*bst)->lchild), x);  // 递归插入到左子树
    }
    else{  // 如果节点应该插入到右子树
        return insertBST(&((*bst)->rchild), x); // 递归插入到右子树
    }
}

 <2>运行结果

 该函数应用于排序树输入时对元素的排序

9:元素查找函数

<1>代码

// 在二叉排序树中查找元素
BiTree searchBST(BiTree bst, int x){
    if (bst == NULL){  // 如果遍历到叶子节点还未找到值
        return NULL;
    }
    else if (x == bst->data){  // 如果找到目标值
        return bst;
    }
    else if (x < bst->data){  // 如果目标值位于左子树
        return searchBST(bst->lchild, x);  // 递归查找左子树
    }
    else{  // 如果目标值位于右子树
        return searchBST(bst->rchild, x);  // 递归查找右子树
    }
}

 <2>运行结果

10:中序遍历函数

// 递归中序遍历
void inorder(BiTree bst){
    if (bst == NULL){
        return;  
    }
    inorder(bst->lchild);
    printf("%d ", bst->data);
    inorder(bst->rchild);
}

11:case5功能函数

因为嫌弃这个部分代码写在.c文件中造成主函数冗余就在.h文件中定义了

<1>代码

//选项5代码
void EX5()
{
  int n, a;
    BiTree bst = NULL;
    printf("请输入整数个数:");
    scanf("%d", &n);
    printf("请输入整数:");
    for (int i=0;i<n;i++){
        scanf("%d", &a);
        insertBST(&bst, a);
    }
    printf("中序遍历序列为:");
    inorder(bst);
    circule://goto跳转的位置
    printf("\n请输入目标值:");
    scanf("%d", &a);
    BiTree res = searchBST(bst, a);
    if (res){
        printf("找到了 %d\n", res->data);
    }
    else{
        printf("未找到该元素,请重新输入:\n");
        goto circule;//goto的使用
    } 
}

 <2>运行结果

12:case7顺序表模块

<1>代码

1:顺序表存储结构定义

//七顺序表实现学生成绩存储以及排序
//------------------------<学生成绩排序>--------------------------------
typedef struct
{
    char name[30];
    int Chinese,Math,English,total;
}STU;//学生信息存储
typedef struct
{
  STU* Element;//存储空间的基地址,顺序表指针动态赋存储空间
  int length;  
}SqList;
#define MAXSIZE 30//限制结构体STU最大容量
#define QUANTITY 21//限制顺序表最大元素个数

2:功能函数

>顺序表初始化函数
int InitList(SqList& L,int N)
{
    int flag2;//标志量
    L.Element=new STU[MAXSIZE];
    L.length=N;//定义学生信息个数
    if(L.Element==NULL)
    {
        return false;
    }
    else
    {
        if(L.length==0)
        {
            printf("您将录入学生信息个数为0!!\n");
        }
        else if(L.length<0)
        {
            printf("非法输入!!\n");
            return false;
        }
        else if(L.length>QUANTITY)//超出顺序表最大容量
        {
            printf("对不起您输入的数据超出数据存储范围!!\n");
            return false;
        }
        else
        {
            for(int i=0;i<L.length;i++)
            {
                circul:
                printf("请输入第%d个学生的姓名、语文、数学、英语的成绩:", i + 1);
				scanf("%s", &L.Element[i].name, sizeof(L.Element[i].name));
 
				scanf("%d", &L.Element[i].Chinese, sizeof(L.Element[i].Chinese));
 
				scanf("%d", &L.Element[i].Math, sizeof(L.Element[i].Math));
			
				scanf("%d", &L.Element[i].English, sizeof(L.Element[i].English));
				if (((L.Element[i].Chinese <= 150) && (L.Element[i].Chinese >= 0)) && ((L.Element[i].Math <= 150) && (L.Element[i].Math >= 0)) && ((L.Element[i].English <= 150) && (L.Element[i].English >= 0)))
				{
					flag2 = 1;
				}
				else
				{
					flag2 = 0;
					printf("输入成绩错误!!请重新录入\n");
					goto circul;
				}
            }
        }
    }
}
>成绩排序函数
//按成绩排序
int Rank(SqList& L)
{
	int arr[5] = { 0 };
	for (int i = 0; i < L.length; i++)
	{
		L.Element[i].total = L.Element[i].Chinese +L.Element[i].Math +L.Element[i].English;
	}//求出总分
	for (int i = 0; i < L.length; i++)
	{
		int count1 = 0;
		for (int j=0; j < L.length; j++)
		{
			if (L.Element[i].total < L.Element[j].total)
			{
				count1 += 1;
			}
            else if(L.Element[i].total == L.Element[j].total)
            {
                count1=count1;
            }
		}
		arr[i] = count1;//利用数组存储名次
	}
	    for (int a = 0; a <= L.length; a++)
		{
			for(int b=0;b<L.length;b++)
			 if(arr[b]==a)//当名次和序号对应时打印顺序表元素
			printf("%s是第%d名\t语文成绩为:%d\t数学成绩为:%d\t英语成绩为:%d\t总成绩为:%d\n",L.Element[b].name, a + 1, L.Element[b].Chinese, L.Element[b].Math,L.Element[b].English, L.Element[b].total);
		}
	return true;
}

 <2>运行结果

包含对分数超过150非法输入的边界定义以及相同分数给予相同排名

三、完整代码

<1> .c文件

#include"Module.h"
int main()
{
    int choice;
    BiTree T,NewT;
    printf("输入二叉树元素,以“#”结束T:\n");
    printf("如果是调佣功能函数5,功能函数7此时输入'#'退出二叉树数据输入就行\n");
    CreateBiTree(T);
    PreOrderTraverse(T);//遍历原二叉树
    printf("\n");
    while(1)
 {
    printf("-------------------------------------------------<请选择要执行的操作>----------------------------------------------\n");
    printf("**\t1:统计二叉树结点数\t2:统计叶子节点数\t\t3:交换左右子树\t\t\t\t\t**\n");
    printf("**\t4:复制二叉树\t\t5:二叉排序树查找\t\t6:退出\t\t7:学生成绩录入并按成绩排序\t**\n");
    printf("-------------------------------------------------------<菜单>------------------------------------------------------\n");
    scanf("%d",&choice);
    switch(choice)
    {
        case 1:
                printf("树节点数为:%d\n",NodeCount(T));
        break;
        case 2:
                printf("叶子结点数为:%d\n",YECOUNT(T));
        break;
        case 3:
               PreOrderTraverse(T);
               printf("\n");
               exchange(T);
               PreOrderTraverse(T);
        break;
        case 4:
                PreOrderTraverse(T);//遍历原二叉树
                Copy(T,NewT);
                printf("\n");
                PreOrderTraverse(NewT);//遍历新二叉树
                printf("\n");
        break;
        case 5:
                EX5();
        break;
        case 6:
                exit(0);
        break;
        case 7:
        SqList L;
        int N,choice;
        printf("请输入您将录入的学生信息个数:\n");
        scanf("%d",&N);
        InitList(L,N);
        Rank(L);
        break;
        default:
                printf("非法输入,请重新输入!!\n");
        break;
    }
 }
}

<2>.h文件

#include<stdio.h>
#include<stdlib.h>
#define TElemType int
typedef struct BiTNode
{
    TElemType data;//节点数据域
    struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
//递归创建树
void CreateBiTree(BiTree &T)
{
    char ch;
    printf("请输入读入的字符:\n");
    scanf("%c",&ch);
    getchar();
    if(ch=='#')
    {
        T=NULL;//递归结束,建空树
    }
    else//递归创建二叉树
    {
        T=new BiTNode;//生成根节点
        T->data = ch;//根节点数据域置为ch
        T->lchild = NULL; // 初始化左子树为空
        T->rchild = NULL; // 初始化右子树为空
        CreateBiTree(T->lchild);//递归创建左子树
        CreateBiTree(T->rchild);//递归创建右子树

    }
}
//递归复制树
void Copy(BiTree T,BiTree &NewT)
{
    //复制一棵和T完全相同的树
    if(T==NULL)
    {
        NewT =NULL;
        return;
    }
    else
    {
        NewT = new BiTNode;
        NewT->data=T->data;//复制根节点
        Copy(T->lchild,NewT->lchild);//递归复制左子树
        Copy(T->rchild,NewT->rchild);//递归复制右子树
    }
}
//递归计算二叉树的结点个数
int NodeCount(BiTree T) {
	if (T)
		return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
	else
		return 0;
 
}
//递归统计叶子节点数
int YECOUNT(BiTree T)
{
	if(T==NULL){
         return 0;
    }
    else{
        if( (YECOUNT(T->lchild)==NULL)&&(YECOUNT(T->rchild)==NULL) ){
		    return 1; 
		}
		else return YECOUNT(T->lchild) + YECOUNT(T->rchild);
    }
}
//交换左右子树
void exchange(BiTree T){/*交换左右子树核心代码*/
	if(T!=NULL){
		BiTree temp;
		temp=T->lchild;
		T->lchild=T->rchild;
		T->rchild=temp;
		exchange(T->lchild);
		exchange(T->rchild);
	}
}
//二叉树先序遍历
void PreOrderTraverse(BiTree T)
{
    if(T == NULL) return;
    printf("%c ",T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}
// 向二叉排序树中插入元素
int insertBST(BiTree *bst, int x){
    if (*bst == NULL){  // 如果二叉排序树为空
        *bst = (BiTree)malloc(sizeof(BiTNode)); // 新建节点
        (*bst)->data = x;
        (*bst)->lchild = (*bst)->rchild = NULL;
        return 1;
    }
    else if ((*bst)->data == x){  // 如果节点已存在
        return 0;
    }
    else if (x < (*bst)->data){  // 如果节点应该插入到左子树
        return insertBST(&((*bst)->lchild), x);  // 递归插入到左子树
    }
    else{  // 如果节点应该插入到右子树
        return insertBST(&((*bst)->rchild), x); // 递归插入到右子树
    }
}

// 在二叉排序树中查找元素
BiTree searchBST(BiTree bst, int x){
    if (bst == NULL){  // 如果遍历到叶子节点还未找到值
        return NULL;
    }
    else if (x == bst->data){  // 如果找到目标值
        return bst;
    }
    else if (x < bst->data){  // 如果目标值位于左子树
        return searchBST(bst->lchild, x);  // 递归查找左子树
    }
    else{  // 如果目标值位于右子树
        return searchBST(bst->rchild, x);  // 递归查找右子树
    }
}
// 递归中序遍历
void inorder(BiTree bst){
    if (bst == NULL){
        return;  
    }
    inorder(bst->lchild);
    printf("%d ", bst->data);
    inorder(bst->rchild);
}
//选项5代码
void EX5()
{
  int n, a;
    BiTree bst = NULL;
    printf("请输入整数个数:");
    scanf("%d", &n);
    printf("请输入整数:");
    for (int i=0;i<n;i++){
        scanf("%d", &a);
        insertBST(&bst, a);
    }
    printf("中序遍历序列为:");
    inorder(bst);
    circule://goto跳转的位置
    printf("\n请输入目标值:");
    scanf("%d", &a);
    BiTree res = searchBST(bst, a);
    if (res){
        printf("找到了 %d\n", res->data);
    }
    else{
        printf("未找到该元素,请重新输入:\n");
        goto circule;//goto的使用
    } 
}
//七顺序表实现学生成绩存储以及排序
//------------------------<学生成绩排序>--------------------------------
typedef struct
{
    char name[30];
    int Chinese,Math,English,total;
}STU;//学生信息存储
typedef struct
{
  STU* Element;//存储空间的基地址,顺序表指针动态赋存储空间
  int length;  
}SqList;
#define MAXSIZE 30//限制结构体STU最大容量
#define QUANTITY 21//限制顺序表最大元素个数
int InitList(SqList& L,int N)
{
    int flag2;//标志量
    L.Element=new STU[MAXSIZE];
    L.length=N;//定义学生信息个数
    if(L.Element==NULL)
    {
        return false;
    }
    else
    {
        if(L.length==0)
        {
            printf("您将录入学生信息个数为0!!\n");
        }
        else if(L.length<0)
        {
            printf("非法输入!!\n");
            return false;
        }
        else if(L.length>QUANTITY)//超出顺序表最大容量
        {
            printf("对不起您输入的数据超出数据存储范围!!\n");
            return false;
        }
        else
        {
            for(int i=0;i<L.length;i++)
            {
                circul:
                printf("请输入第%d个学生的姓名、语文、数学、英语的成绩:", i + 1);
				scanf("%s", &L.Element[i].name, sizeof(L.Element[i].name));
 
				scanf("%d", &L.Element[i].Chinese, sizeof(L.Element[i].Chinese));
 
				scanf("%d", &L.Element[i].Math, sizeof(L.Element[i].Math));
			
				scanf("%d", &L.Element[i].English, sizeof(L.Element[i].English));
				if (((L.Element[i].Chinese <= 150) && (L.Element[i].Chinese >= 0)) && ((L.Element[i].Math <= 150) && (L.Element[i].Math >= 0)) && ((L.Element[i].English <= 150) && (L.Element[i].English >= 0)))
				{
					flag2 = 1;
				}
				else
				{
					flag2 = 0;
					printf("输入成绩错误!!请重新录入\n");
					goto circul;
				}
            }
        }
    }
}
//按成绩排序
int Rank(SqList& L)
{
	int arr[5] = { 0 };
	for (int i = 0; i < L.length; i++)
	{
		L.Element[i].total = L.Element[i].Chinese +L.Element[i].Math +L.Element[i].English;
	}//求出总分
	for (int i = 0; i < L.length; i++)
	{
		int count1 = 0;
		for (int j=0; j < L.length; j++)
		{
			if (L.Element[i].total < L.Element[j].total)
			{
				count1 += 1;
			}
            else if(L.Element[i].total == L.Element[j].total)
            {
                count1=count1;
            }
		}
		arr[i] = count1;//利用数组存储名次
	}
	    for (int a = 0; a <= L.length; a++)
		{
			for(int b=0;b<L.length;b++)
			 if(arr[b]==a)//当名次和序号对应时打印顺序表元素
			printf("%s是第%d名\t语文成绩为:%d\t数学成绩为:%d\t英语成绩为:%d\t总成绩为:%d\n",L.Element[b].name, a + 1, L.Element[b].Chinese, L.Element[b].Math,L.Element[b].English, L.Element[b].total);
		}
	return true;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值