数据结构课设—查找、排序、文件—二叉排序树与文件操作

功能要求:
(1)从键盘输入一组学生记录建立二叉排序树;
(2)*二叉排序树存盘;
(3)*由文件恢复内存的二叉排序树;
(4)中序遍历二叉排序树;
(5)求二叉排序树深度;
(6)求二叉排序树的所有节点数和叶子节点数;
(7)向二叉排序树插入一条学生记录;
(8)从二叉排序树中删除一条学生记录;
(9)从二叉排序树中查询一条学生记录;
(10)以广义表的形式输出二叉排序树
//定义学生记录类型
Struct student
{
Char num[6]; //学号
Int grade; //成绩
};
//定义二叉排序树节点值的类型为学生记录类型
typedef student ElemType;
//定义二叉排序树的节点类型
typedef Struct BSTNode
{
ElemType data;
Struct BSTNode *left;
Struct BSTNode *rchild;
} BSTNode;

#include <bits/stdc++.h>
#define FN "D:\\BST.txt"
//二叉排序树
using namespace std;
typedef struct student
{
    char  num[6];  //学号
    int   grade;   //成绩
} ElemType;
typedef struct BTnode
{
    ElemType data;
    BTnode *lchild,*rchild;
} BTnode,*BTtree;
ElemType a[105];
BTtree creatBTtree()
{
    BTtree bt=NULL;
    return bt;
}
int nodenum(BTtree T)//求结点数
{
    int sum=0;
    if(!T)
    {
        return 0;
    }
    else
    {
        sum=1+nodenum(T->lchild)+nodenum(T->rchild);
    }
    return sum;
}
int leafnodenum(BTtree T)//求结点数
{
    int sum=0;
    if(!T)
    {
        return 0;
    }
    else if((T->lchild==NULL)&&(T->rchild==NULL))
    {
        return 1;
    }
    else
    {
        return leafnodenum(T->lchild)+leafnodenum(T->rchild);
    }
    return sum;
}
void InOrderTraverseBTtree(BTtree T)//中序遍历
{
    if(T)
    {
        InOrderTraverseBTtree(T->lchild);
        printf("学号:%s 成绩:%d\n",T->data.num,T->data.grade);
        InOrderTraverseBTtree(T->rchild);
    }
}
int Depth(BTtree T)
{
    if(!T)return 0;
    else
    {
        int m=Depth(T->lchild);
        int n=Depth(T->rchild);
        if(m>n){return m+1;}
        else{return n+1;}
    }
}

int SearchBST(BTtree T,char no[])//寻找元素是否存在
//T为当前根节点,e为要查找的元素,f为T的父节点,p为找到的元素节点或没找到时的根节点
{
    queue<BTtree>q;
    q.push(T);
    while(!q.empty())
    {
        BTtree t=q.front();
        q.pop();
        if (strcmp((t->data.num),no)==0)
        {
            return t->data.grade;
        }
        if (t->lchild)
        {
            q.push(t->lchild);
        }
        if (t->rchild)
        {
            q.push(t->rchild);
        }
    }
    return 0;
}

int InsertBST(BTtree &T,char no[],int e)//插入函数
{
    BTtree s=NULL,p,q=NULL;
    s=new BTnode;
    strcpy(s->data.num,no);
    s->data.grade=e;
    s->lchild=s->rchild=NULL;
    if(!T)//若树空
    {
        T=s;
        return 1;
    }
    if(SearchBST(T,no))//如果该元素已在树中
    {
        return 0;
    }
    p=T;
    while(p)
    {
        q=p;
        if(p->data.grade > e)//如果该元素比根节点值小
        {
            p=p->lchild;
        }
        else//如果该元素比根节点值大
        {
            p=p->rchild;
        }
    }
    if(q->data.grade>e)
    {
        q->lchild=s;
        return 1;
    }
    else
    {
        q->rchild=s;
        return 1;
    }
    return 0;
}


int Delete(BTtree *p)//删除函数的具体操作
{
    BTtree q,s;
    if((*p)->rchild==NULL)//缺右子树
    {
        q=*p;
        *p=(*p)->lchild;//用左子女替代
        free(q);
    }
    else if((*p)->lchild==NULL)//缺左子树
    {
        q=*p;
        *p=(*p)->rchild;//用右子女替代
        free(q);
    }
    else//左,右子树都存在
    {
        q=*p;
        s=(*p)->lchild;
        while(s->rchild)
        {
            q=s;
            s=s->rchild;
        }
        (*p)->data=s->data;//用左子树的最大节点代替
        if(*p!=q)
        {
            q->rchild=s->lchild;
        }
        else
        {
            q->lchild=s->lchild;
        }
        free(s);
    }
    return 1;
}
int DeleteBST(BTtree *T,int e)//删除函数
{
    if(!*T)
    {
        return -1;
    }
    else
    {
        if((*T)->data.grade==e)
        {
            return Delete(T);
        }
        else if(e<(*T)->data.grade)
        {
            return DeleteBST(&(*T)->lchild,e);
        }
        else
        {
            return DeleteBST(&(*T)->rchild,e);
        }
    }
}

int f_write(BTtree T)
{
    FILE *fp;
    if((fp=fopen(FN,"w+"))==NULL)
    {
        printf("fail open!\n");
        return -1;
    }
    queue<BTtree>q;
    q.push(T);
    while(!q.empty())
    {
        BTtree t=q.front();
        q.pop();
        fprintf(fp,"%s %d\n",t->data.num,t->data.grade);
        printf("%s %d\n",t->data.num,t->data.grade);
        if (t->lchild)
        {
            q.push(t->lchild);
        }
        if (t->rchild)
        {
            q.push(t->rchild);
        }
    }
    cout<<"文件存储成功!"<<endl;
    fclose(fp);
    return 0;
}

int f_read(BTtree &T)
{
    FILE *fp;
    if((fp=fopen(FN,"r+"))==NULL)
    {
        printf("fail open!\n");
        return -1;
    }
    int x;
    char str[6];
    while (!feof(fp))
    {
        fscanf(fp,"%s %d\n",str,&x);
        //str[6]='\0';
        InsertBST(T,str,x);
    }
    cout<<"文件打开成功!"<<endl;
    fclose(fp);
    return 0;
}

void Put(BTtree T)//以广义表形式输出
{
    if(T!=NULL)
    {
        //cout<<"(";
        cout<<T->data.num;
        if(T->lchild!=NULL||T->rchild!=NULL)
        {
            cout<<"(";
            Put(T->lchild);
            if(T->rchild!=NULL)
            {
                cout<<",";
            }
            Put(T->rchild);
            cout<<")";
        }
    }
}
/*
二叉树的广义表示形式:

a:表示根节点为a,左右节点均为空

a(b):表示根节点为a,左节点为b,右节点为空

a(,c):表示根节点为a,左节点为空,右节点为c

a(b,c)表示父节点为a,左子节点与右子节点分别为b和c
*/

void menu()
{
    printf ("\n1.键盘输入一组学生记录建立二叉排序树\n");
    printf ("2.二叉排序树存盘\n");
    printf ("3.由文件恢复内存的二叉排序树\n");
    printf ("4.中序遍历二叉排序树\n");
    printf ("5.求二叉排序树深度\n");
    printf ("6.求二叉排序树的所有节点数和叶子节点数\n");
    printf ("7.向二叉排序树插入一条学生记录\n");
    printf ("8.从二叉排序树中删除一条学生记录\n");
    printf ("9.从二叉排序树中查询一条学生记录\n");
    printf ("10.以广义表的形式输出二叉排序树\n\n");
}


int main()
{
    printf("--------二叉排序树存储学生信息系统--------\n");
    BTtree T;
    T=creatBTtree();
    int ch;
    while (1)
    {
        menu();
        printf("请输入操作序号:\n");
        cin>>ch;
        switch(ch)
        {
        case 1:
            int n;
            ElemType x;
            printf("请输入你要记录的学生信息个数:");
            cin>>n;
            for(int i=1; i<=n; i++)
            {
                printf("请输入你要记录的学生信息:");
                cin>>x.num>>x.grade;
                InsertBST(T,x.num,x.grade);
            }
            break;
        case 2:
            f_write(T);
            break;
        case 3:
            f_read(T);
            break;
        case 4:
            printf("\n中序遍历该二叉排序树的结果为:\n");
            InOrderTraverseBTtree(T);
            break;
        case 5:
            printf("\n二叉树深度为:%d\n",Depth(T));
            break;
        case 6:
            printf("\n二叉树结点数为:%d\n",nodenum(T));
            printf("\n二叉树叶子结点数为:%d\n",leafnodenum(T));
            break;
        case 7:
            char s[6];
            int score;
            printf ("请输入插入学生学号\n");
            cin>>s;
            if(SearchBST(T,s))
            {
                printf("该学生信息已经存在,无法进行插入操作!\n");
                break;
            }
            printf ("请输入插入学生成绩\n");
            cin>>score;
            InsertBST(T,s,score);
            printf ("进行插入操作后的学生信息为\n");
            InOrderTraverseBTtree(T);
            break;
        case 8:
            printf ("请输入删除学生学号\n");
            char Del[6];
            cin>>Del;
            if(!SearchBST(T,Del))
            {
                printf("该数不存在,无法进行删除操作!\n");
            }
            else
            {
                DeleteBST(&T,SearchBST(T,Del));
                printf ("进行删除操作后的学生信息为\n");
                InOrderTraverseBTtree(T);
            }
            break;
        case 9:
            printf ("请输入查找学生学号\n");
            char no[6];
            cin>>no;
            if(SearchBST(T,no))
            {
                printf ("学号为 %s 的同学成绩为 :%d\n",no,SearchBST(T,no));
            }
            else
            {
                printf("没有找到该学生\n");
            }
            break;
        case 10:
            printf("\n以广义表形式该二叉排序树的结果为:");
            Put(T);
            break;
        default:
            printf("输入序号有误,请重新输入\n");
            break;
        }
    }
    return 0;
}

/*
5
1901 98
1902 100
1903 87
1904 95
1905 65
*/

  • 2
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值