因为嫌麻烦不想分开写所以把三个部分写在了一起,本例程内容包括普通二叉树、二叉排序树和顺序表三部分,在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;
}