此乃数据结构作业
//
程序名: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
;
}