用SBT实现一个学生健康管理系统...
此乃数据结构作业
// 程序名:student.cpp
// 程序功能:用Size Balanced Tree实现一个学生管理系统
// 作者:zgmf_x20a
// 日期:2008.11.18
// 版本:1.0
// 说明:SBT是一颗高度平衡的二叉搜索树,它的所有动态操作,包括查找,求最小值,最大值,前驱,后继,
// 插入和删除,在最坏的情况下都保持在O(log n),而且实现简单
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream fin;
ofstream fout;
struct Datatype{
int ID;
string name;
string birth;
string sex;
string health;
void operator=(Datatype temp){
ID=temp.ID;
name=temp.name;
birth=temp.birth;
sex=temp.sex;
health=temp.health;
}
};
inline void InputData(Datatype *a){
cin>>a->ID>>a->name>>a->birth>>a->sex>>a->health;
}
inline void OutputData(Datatype *a){
cout<<a->ID<<'\t'<<a->name<<'\t'<<a->birth<<"\t\t"<<a->sex<<'\t'<<a->health<<'\n';
}
struct SBTNode{
SBTNode *lc,*rc;
int sz;
Datatype key;
SBTNode(Datatype* _key){
key=*_key;
sz=1;
lc=NULL;
rc=NULL;
}
};
///////////////////////////////
SBTNode* SBTSearch(SBTNode* T,int ID);
void SBTInsert(SBTNode* &T,SBTNode* x);//修改了树的结构,故参数需引用
Datatype* SBTDel(SBTNode* &T,int ID);//
SBTNode* SBTPred(SBTNode* T,int ID);
SBTNode* SBTSucc(SBTNode* T,int ID);
SBTNode* SBTSelect(SBTNode* T,int k);
int SBTRank(SBTNode* T,int ID);
void InOrder(SBTNode* T);
//////////////////////////////
void RightRotate(SBTNode* &x){
int res=0;
SBTNode* y=x->lc;
x->lc=y->rc;
y->rc=x;
y->sz=x->sz;
if(x->lc!=NULL)
res+=x->lc->sz;
if(x->rc!=NULL)
res+=x->rc->sz;
x->sz=res+1;
x=y;
}
void LeftRotate(SBTNode* &x){
int res=0;
SBTNode* y=x->rc;
x->rc=y->lc;
y->lc=x;
y->sz=x->sz;
if(x->lc!=NULL)
res+=x->lc->sz;
if(x->rc!=NULL)
res+=x->rc->sz;
x->sz=res+1;
x=y;
}
SBTNode* SBTSearch(SBTNode* T,int ID){
if(!T || ID==T->key.ID)
return T;
if(ID<T->key.ID)
return SBTSearch(T->lc,ID);
else
return SBTSearch(T->rc,ID);
}
void Maintain(SBTNode* &T,bool RightDeeper){
if(T==NULL || T->sz<=2)
return;
if(!RightDeeper){
if(T->lc && T->lc->lc && ( T->rc==NULL || T->lc->lc->sz>T->rc->sz))
RightRotate(T);
else if(T->lc && T->lc->rc && (T->rc==NULL || T->lc->rc->sz>T->rc->sz)){
LeftRotate(T->lc);
RightRotate(T);
}
else
return;
}
else{
if(T->rc && T->rc->rc && ( T->lc==NULL || T->rc->rc->sz>T->lc->sz))
LeftRotate(T);
else if(T->rc && T->rc->lc && (T->lc==NULL || T->rc->lc->sz>T->lc->sz)){
RightRotate(T->rc);
LeftRotate(T);
}
else
return;
}
//if(T->lc->sz>2)
Maintain(T->lc,false);
//if(T->rc->sz>2)
Maintain(T->rc,true);
//if(T->sz>2)
Maintain(T,false);
//if(T->sz>2)
Maintain(T,true);
}
void SBTInsert(SBTNode* &T,SBTNode* x){
if(T==NULL){
T=x;
return;
}
T->sz++;
if(x->key.ID<T->key.ID)
SBTInsert(T->lc,x);
else
SBTInsert(T->rc,x);
//if(T->sz>2)
Maintain(T,x->key.ID>=T->key.ID);
}
Datatype* SBTDel(SBTNode* &T,int ID){
Datatype *record,*temp;
if(T->sz<=2){
record=new Datatype;
*record=T->key;
//T=T->lc+T->rc;
T=T->lc?T->lc:T->rc;
return record;
}
T->sz--;
if(ID==T->key.ID){
int res=0;
record=SBTDel(T->lc,ID+1);
temp=new Datatype;
*temp=T->key;
T->key=*record;//
*record=*temp;
if(T->lc)
res+=T->lc->sz;
if(T->rc)
res+=T->rc->sz;
//T->sz=record->sz;//
T->sz=res+1;
Maintain(T,true);
}
else if(ID<T->key.ID)
record=SBTDel(T->lc,ID);
else
record=SBTDel(T->rc,ID);
Maintain(T,ID<T->key.ID);
return record;
}
SBTNode* SBTPred(SBTNode* T,int ID){
if(!T)
return NULL;
if(ID<=T->key.ID)
return SBTPred(T->rc,ID);
else{
SBTNode* pred=SBTPred(T->rc,ID);
return (pred?pred:T);
}
}
SBTNode* SBTSucc(SBTNode* T,int ID){
if(!T)
return NULL;
if(ID>=T->key.ID)
return SBTSucc(T->rc,ID);
else{
SBTNode* succ=SBTSucc(T->lc,ID);
return (succ?succ:T);
}
}
SBTNode* SBTSelect(SBTNode* T,int k){
if(k==T->lc->sz+1)
return T;
if(k<=T->lc->sz)
return SBTSelect(T->lc,k);
else
return SBTSelect(T->rc,k-1-T->lc->sz);
}
int SBTRank(SBTNode* T,int ID){
if(T==NULL)
return 1;
if(ID<=T->key.ID)
return SBTRank(T->lc,ID);
else
return T->lc->sz+1+SBTRank(T->rc,ID);
}
void InOrder(SBTNode *T){
if(T==NULL)
return;
InOrder(T->lc);
OutputData(&(T->key));
InOrder(T->rc);
}
void InOrder_file(SBTNode *T){
if(T==NULL)
return;
InOrder_file(T->lc);
//fout.write((char*)&(T->key),sizeof(T->key));
fout<<T->key.ID<<' '<<T->key.name<<' '<<T->key.birth<<' '<<T->key.sex<<' '<<T->key.health<<"\n";
InOrder_file(T->rc);
}
////////////////////////////////////////////////
void menu(){
cout<<"\n-----------菜单---------------\n";
cout<<"|1.新建学生健康表\n";
cout<<"|2.向学生健康表插入学生信息\n";
cout<<"|3.在健康表删除学生信息\n";
cout<<"|4.从文件中读取健康表信息\n";
cout<<"|5.向文件写入学生健康表信息\n";
cout<<"|6.在健康表中查询学生信息(按学生学号来进行查找)\n";
cout<<"|7.在屏幕中输出全部学生信息\n";
cout<<"|8.退出\n";
cout<<"------------------------------\n\n";
cout<<"请输入一种操作:\n";
}
bool input(int &x){
cin>>x;
if(!cin.good()){
cin.clear();
cin.ignore();
return false;
}
return true;
}
int main(){
int chose,i,n,ID;
char ch;
bool flag=true;
system("color 74");
SBTNode *T,*temp;
Datatype *datatemp;
while(flag){
menu();
while(!(input(chose) && chose>=1 && chose<=11))
cout<<"输入有误,请重新输入:";
switch(chose){
case 1:
T=NULL;
cout<<"请输入将要输入学生数目:";
while(!input(n))
cout<<"输入有误,请重新输入:";
cout<<"请顺序输入学号、姓名、出生日期、性别、身体状况(用空格区分):\n";
for(i=1;i<=n;i++){
cout<<"请输入第"<<i<<"个学生的数据:\n";
datatemp=new Datatype;
//cin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health;
InputData(datatemp);
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
}
cout<<"建表成功!\n\n";
system("PAUSE");
break;
case 2:
cout<<"顺序输入学号、姓名、出生日期、性别、身体状况(用空格区分):\n";
datatemp=new Datatype;
//cin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health;
InputData(datatemp);
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
cout<<"插入成功!\n\n";
system("PAUSE");
break;
case 3:
if(T==NULL){
cout<<"学生健康表已为空!\n";
system("PAUSE");
break;
}
cout<<"请输入需要删除的学生的学号(若该学号不存在则删除下一个较大的学号):";
cin>>ID;
cout<<"你将要删除的学生信息如下:\n";
datatemp=SBTDel(T,ID);
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
//cout<<datatemp->ID<<'\t'<<datatemp->name<<'\t'<<datatemp->birth<<'\t'<<datatemp->sex<<'\t'<<datatemp->health<<'\n';
OutputData(datatemp);
cout<<"确定删除?(Y/N):";
cin>>ch;
if(ch=='N'){
temp=new SBTNode(datatemp);
temp->lc=temp->rc=NULL;
temp->sz=1;
SBTInsert(T,temp);
}
else
cout<<"删除成功!\n\n";
system("PAUSE");
break;
case 4:
fin.clear();
fin.open("student.dat",ios::in | ios::binary);
if(!fin)
cout<<"文件打开失败!请检查student.dat是否在根目录中。\n\n";
else{
T=NULL;
datatemp=new Datatype;
while(fin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health){
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
datatemp=new Datatype;
}
cout<<"文件读入成功!\n\n";
}
fin.close();
system("PAUSE");
break;
case 5:
fout.clear();
fout.open("student.dat",ios::out | ios::binary);
if(!fout)
cout<<"文件保存失败!\n\n";
else{
InOrder_file(T);
cout<<"文件保存成功!\n\n";
}
fout.close();
system("PAUSE");
break;
case 6:
cout<<"请输入目标学生的学号:";
cin>>ID;
temp=SBTSearch(T,ID);
if(temp==NULL)
cout<<"该学生不存在!\n";
else{
cout<<"该学生的资料如下:\n";
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
OutputData(&(temp->key));
}
cout<<"\n";
system("PAUSE");
break;
case 7:
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
InOrder(T);
cout<<"\n";
system("PAUSE");
break;
case 8:
flag=false;
break;
}
}
return 0;
}
// 程序功能:用Size Balanced Tree实现一个学生管理系统
// 作者:zgmf_x20a
// 日期:2008.11.18
// 版本:1.0
// 说明:SBT是一颗高度平衡的二叉搜索树,它的所有动态操作,包括查找,求最小值,最大值,前驱,后继,
// 插入和删除,在最坏的情况下都保持在O(log n),而且实现简单
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream fin;
ofstream fout;
struct Datatype{
int ID;
string name;
string birth;
string sex;
string health;
void operator=(Datatype temp){
ID=temp.ID;
name=temp.name;
birth=temp.birth;
sex=temp.sex;
health=temp.health;
}
};
inline void InputData(Datatype *a){
cin>>a->ID>>a->name>>a->birth>>a->sex>>a->health;
}
inline void OutputData(Datatype *a){
cout<<a->ID<<'\t'<<a->name<<'\t'<<a->birth<<"\t\t"<<a->sex<<'\t'<<a->health<<'\n';
}
struct SBTNode{
SBTNode *lc,*rc;
int sz;
Datatype key;
SBTNode(Datatype* _key){
key=*_key;
sz=1;
lc=NULL;
rc=NULL;
}
};
///////////////////////////////
SBTNode* SBTSearch(SBTNode* T,int ID);
void SBTInsert(SBTNode* &T,SBTNode* x);//修改了树的结构,故参数需引用
Datatype* SBTDel(SBTNode* &T,int ID);//
SBTNode* SBTPred(SBTNode* T,int ID);
SBTNode* SBTSucc(SBTNode* T,int ID);
SBTNode* SBTSelect(SBTNode* T,int k);
int SBTRank(SBTNode* T,int ID);
void InOrder(SBTNode* T);
//////////////////////////////
void RightRotate(SBTNode* &x){
int res=0;
SBTNode* y=x->lc;
x->lc=y->rc;
y->rc=x;
y->sz=x->sz;
if(x->lc!=NULL)
res+=x->lc->sz;
if(x->rc!=NULL)
res+=x->rc->sz;
x->sz=res+1;
x=y;
}
void LeftRotate(SBTNode* &x){
int res=0;
SBTNode* y=x->rc;
x->rc=y->lc;
y->lc=x;
y->sz=x->sz;
if(x->lc!=NULL)
res+=x->lc->sz;
if(x->rc!=NULL)
res+=x->rc->sz;
x->sz=res+1;
x=y;
}
SBTNode* SBTSearch(SBTNode* T,int ID){
if(!T || ID==T->key.ID)
return T;
if(ID<T->key.ID)
return SBTSearch(T->lc,ID);
else
return SBTSearch(T->rc,ID);
}
void Maintain(SBTNode* &T,bool RightDeeper){
if(T==NULL || T->sz<=2)
return;
if(!RightDeeper){
if(T->lc && T->lc->lc && ( T->rc==NULL || T->lc->lc->sz>T->rc->sz))
RightRotate(T);
else if(T->lc && T->lc->rc && (T->rc==NULL || T->lc->rc->sz>T->rc->sz)){
LeftRotate(T->lc);
RightRotate(T);
}
else
return;
}
else{
if(T->rc && T->rc->rc && ( T->lc==NULL || T->rc->rc->sz>T->lc->sz))
LeftRotate(T);
else if(T->rc && T->rc->lc && (T->lc==NULL || T->rc->lc->sz>T->lc->sz)){
RightRotate(T->rc);
LeftRotate(T);
}
else
return;
}
//if(T->lc->sz>2)
Maintain(T->lc,false);
//if(T->rc->sz>2)
Maintain(T->rc,true);
//if(T->sz>2)
Maintain(T,false);
//if(T->sz>2)
Maintain(T,true);
}
void SBTInsert(SBTNode* &T,SBTNode* x){
if(T==NULL){
T=x;
return;
}
T->sz++;
if(x->key.ID<T->key.ID)
SBTInsert(T->lc,x);
else
SBTInsert(T->rc,x);
//if(T->sz>2)
Maintain(T,x->key.ID>=T->key.ID);
}
Datatype* SBTDel(SBTNode* &T,int ID){
Datatype *record,*temp;
if(T->sz<=2){
record=new Datatype;
*record=T->key;
//T=T->lc+T->rc;
T=T->lc?T->lc:T->rc;
return record;
}
T->sz--;
if(ID==T->key.ID){
int res=0;
record=SBTDel(T->lc,ID+1);
temp=new Datatype;
*temp=T->key;
T->key=*record;//
*record=*temp;
if(T->lc)
res+=T->lc->sz;
if(T->rc)
res+=T->rc->sz;
//T->sz=record->sz;//
T->sz=res+1;
Maintain(T,true);
}
else if(ID<T->key.ID)
record=SBTDel(T->lc,ID);
else
record=SBTDel(T->rc,ID);
Maintain(T,ID<T->key.ID);
return record;
}
SBTNode* SBTPred(SBTNode* T,int ID){
if(!T)
return NULL;
if(ID<=T->key.ID)
return SBTPred(T->rc,ID);
else{
SBTNode* pred=SBTPred(T->rc,ID);
return (pred?pred:T);
}
}
SBTNode* SBTSucc(SBTNode* T,int ID){
if(!T)
return NULL;
if(ID>=T->key.ID)
return SBTSucc(T->rc,ID);
else{
SBTNode* succ=SBTSucc(T->lc,ID);
return (succ?succ:T);
}
}
SBTNode* SBTSelect(SBTNode* T,int k){
if(k==T->lc->sz+1)
return T;
if(k<=T->lc->sz)
return SBTSelect(T->lc,k);
else
return SBTSelect(T->rc,k-1-T->lc->sz);
}
int SBTRank(SBTNode* T,int ID){
if(T==NULL)
return 1;
if(ID<=T->key.ID)
return SBTRank(T->lc,ID);
else
return T->lc->sz+1+SBTRank(T->rc,ID);
}
void InOrder(SBTNode *T){
if(T==NULL)
return;
InOrder(T->lc);
OutputData(&(T->key));
InOrder(T->rc);
}
void InOrder_file(SBTNode *T){
if(T==NULL)
return;
InOrder_file(T->lc);
//fout.write((char*)&(T->key),sizeof(T->key));
fout<<T->key.ID<<' '<<T->key.name<<' '<<T->key.birth<<' '<<T->key.sex<<' '<<T->key.health<<"\n";
InOrder_file(T->rc);
}
////////////////////////////////////////////////
void menu(){
cout<<"\n-----------菜单---------------\n";
cout<<"|1.新建学生健康表\n";
cout<<"|2.向学生健康表插入学生信息\n";
cout<<"|3.在健康表删除学生信息\n";
cout<<"|4.从文件中读取健康表信息\n";
cout<<"|5.向文件写入学生健康表信息\n";
cout<<"|6.在健康表中查询学生信息(按学生学号来进行查找)\n";
cout<<"|7.在屏幕中输出全部学生信息\n";
cout<<"|8.退出\n";
cout<<"------------------------------\n\n";
cout<<"请输入一种操作:\n";
}
bool input(int &x){
cin>>x;
if(!cin.good()){
cin.clear();
cin.ignore();
return false;
}
return true;
}
int main(){
int chose,i,n,ID;
char ch;
bool flag=true;
system("color 74");
SBTNode *T,*temp;
Datatype *datatemp;
while(flag){
menu();
while(!(input(chose) && chose>=1 && chose<=11))
cout<<"输入有误,请重新输入:";
switch(chose){
case 1:
T=NULL;
cout<<"请输入将要输入学生数目:";
while(!input(n))
cout<<"输入有误,请重新输入:";
cout<<"请顺序输入学号、姓名、出生日期、性别、身体状况(用空格区分):\n";
for(i=1;i<=n;i++){
cout<<"请输入第"<<i<<"个学生的数据:\n";
datatemp=new Datatype;
//cin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health;
InputData(datatemp);
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
}
cout<<"建表成功!\n\n";
system("PAUSE");
break;
case 2:
cout<<"顺序输入学号、姓名、出生日期、性别、身体状况(用空格区分):\n";
datatemp=new Datatype;
//cin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health;
InputData(datatemp);
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
cout<<"插入成功!\n\n";
system("PAUSE");
break;
case 3:
if(T==NULL){
cout<<"学生健康表已为空!\n";
system("PAUSE");
break;
}
cout<<"请输入需要删除的学生的学号(若该学号不存在则删除下一个较大的学号):";
cin>>ID;
cout<<"你将要删除的学生信息如下:\n";
datatemp=SBTDel(T,ID);
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
//cout<<datatemp->ID<<'\t'<<datatemp->name<<'\t'<<datatemp->birth<<'\t'<<datatemp->sex<<'\t'<<datatemp->health<<'\n';
OutputData(datatemp);
cout<<"确定删除?(Y/N):";
cin>>ch;
if(ch=='N'){
temp=new SBTNode(datatemp);
temp->lc=temp->rc=NULL;
temp->sz=1;
SBTInsert(T,temp);
}
else
cout<<"删除成功!\n\n";
system("PAUSE");
break;
case 4:
fin.clear();
fin.open("student.dat",ios::in | ios::binary);
if(!fin)
cout<<"文件打开失败!请检查student.dat是否在根目录中。\n\n";
else{
T=NULL;
datatemp=new Datatype;
while(fin>>datatemp->ID>>datatemp->name>>datatemp->birth>>datatemp->sex>>datatemp->health){
temp=new SBTNode(datatemp);
SBTInsert(T,temp);
datatemp=new Datatype;
}
cout<<"文件读入成功!\n\n";
}
fin.close();
system("PAUSE");
break;
case 5:
fout.clear();
fout.open("student.dat",ios::out | ios::binary);
if(!fout)
cout<<"文件保存失败!\n\n";
else{
InOrder_file(T);
cout<<"文件保存成功!\n\n";
}
fout.close();
system("PAUSE");
break;
case 6:
cout<<"请输入目标学生的学号:";
cin>>ID;
temp=SBTSearch(T,ID);
if(temp==NULL)
cout<<"该学生不存在!\n";
else{
cout<<"该学生的资料如下:\n";
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
OutputData(&(temp->key));
}
cout<<"\n";
system("PAUSE");
break;
case 7:
cout<<"学号\t姓名\t出生日期\t性别\t身体状况\n";
InOrder(T);
cout<<"\n";
system("PAUSE");
break;
case 8:
flag=false;
break;
}
}
return 0;
}