资源描述
一、课题名称
电脑存储构造设计与实现(树,查找)
二、重要内容
电脑存储构造设计与实现重要是模仿“我电脑”中硬盘信息建立、查找、插入、修改、删除等功能。可。基本功能如下:
(1)硬盘初始化信息:我电脑(根结点)。
(2)硬盘格式化:为我电脑分区,分区个数由后台终端输入决定,每个硬盘分区信息涉及卷名、文献系统类型、容量等。
(3)文献或文献夹添加:即创立某个分区孩子结点信息(文献(夹)),孩子结点数目由控制台端给出,信息涉及文献(夹)名,文献(夹)大小,所有文献(夹)文献名此处不能重复。 创立好文献夹中还能创立其孩子结点信息(文献(夹))。
(4)文献或文献夹信息修改:可以修改某一文献或文献夹信息,涉及名字和大小。
(5)文献或文献夹查询:查询某一文献或文献夹详细途径。(从我电脑开始)
(6)文献或文献夹删除:删除此文献,如果是文献夹,若其有后裔,将删除其所有后裔成员(文献或文献夹)。
三、课题设计基本思想,原理和算法描述
此课题重要用树来建立电脑存储构造设计,并用树有关知识,递归思想贯穿始终,实现硬盘初始化和格式化,并在分区里实现文献(夹)添加、修改、查询、删除功能。
主函数和总界面:
void menu()
{
system("cls");
printf(" ******************************************************\n");
printf(" * 欢迎进入电脑存储设计与实现系统! *\n");
printf(" * ----------------- * \n");
printf(" * 1.硬盘初始化信息: *\n");
printf(" * 2.硬盘格式化信息: * \n");
printf(" * 3.添加文献(夹)信息: *\n");
printf(" * 4.修改文献(夹)信息: * \n");
printf(" * 5.查询文献(夹)信息: *\n");
printf(" * 6.删除文献(夹)信息 * \n");
printf(" * 7.退出 *\n");
printf(" ******************************************************\n");
printf("请选取功能操作号:"); //选取相应数字实现相应功能项
}
void main()
{
TSBNode *b;
while(1)
{
menu();
int c;
scanf("%d",&c);
switch(c)
{
case 1:CreateBTNode(b);break;
case 2:areaTSBNode(b);break;
case 3:Add(b);break;
case 4:Change(b);break;
case 5:Search(b);break;
case 6:Delete(b);break;
case 7:return;
default:printf("选取有误,请重新选取!\n");
}
}
}
硬盘初始化中:直接输入主盘名字,并将此名字赋给根节点。
void CreateBTNode(TSBNode *&b) //硬盘初始化信息 #### 1 初始化 ####
{
system("cls");
printf(" ********欢迎来到硬盘初始化信息界面 !********\n");
printf("\n");
b=NULL;
b=(TSBNode *)malloc(sizeof(TSBNode));
printf("请输入主盘名字:");
scanf("%s",&b->data.name);
b->child=b->brother=NULL;
printf("初始化成功!\n");
chushi=1;
system("pause");//按回车键继续
}
硬盘格式化中:一方面输入主盘名字,判断与否存在此主盘,同步也判断与否进行硬盘初始化,是话继续,否则返回初始化界面。判断结束后,输入需要添加分区数目,一种一种地输入信息。此期间会判断与否重复,重复话重新输入。最后在for循环里,对每个分区和根节点建立关系。
void areaTSBNode(TSBNode *&b)//硬盘格式化 #### 2 格式化 ####
{
system("cls");
printf(" ********欢迎来到硬盘格式化信息界面!********\n");
printf("\n");
TSBNode *p[MAXCHILD];
char name[MAX]; //定义数组指针
printf("请输入需要添加分区主盘名字:");
scanf("%s",&name);
if(chushi==0) //判断与否进行初始化,否则返回初始化界面
{
printf("请先进行硬盘初始化!\n");
system("pause"); //按回车键继续;
CreateBTNode(b);
return;
}
if(strcmp(b->data.name,name)!=0) //判断与否存在
{
printf("不存在此主盘,请重新输入!\n");
printf("请输入需要添加分区主盘名字:");
scanf("%s",&name);
}
int childnum; //定义分区数目
printf("请输入分区数目:");
scanf("%d",&childnum);
for(int i=1;i<=childnum;i++) //for语句依次添加信息
{
p[i]=(TSBNode *)malloc(sizeof(TSBNode));
p[i]->child=p[i]->brother=NULL;
printf("请输入第%d个分区信息:\n",i);
printf("卷名:");
scanf("%s",&p[i]->data.name);
printf("类型:");
scanf("%s",&p[i]->data.type);
printf("容量:");
scanf("%s",&p[i]->data.volume);
if(FindNode(b,p[i]->data.name)!=NULL) //判断与否重复
{
printf("分区卷名重复,请重新输入!\n");
printf("卷名:");
scanf("%s",&p[i]->data.name);
printf("类型:");
scanf("%s",&p[i]->data.type);
printf("容量:");
scanf("%s",&p[i]->data.volume);
}
if(i==1)
b->child=p[i];
else
p[i-1]->brother=p[i];
}
printf("格式化成功!\n");geshi=1;
system("pause"); //按回车键继续;
}
文献(夹)添加中:同格式化,一方面输入分区或文献(夹)名字,判断与否存在此分区或文献(夹),同步也判断与否进行硬盘格式化,是话继续,否则返回格式化界面。还增长了需要添加文献输入,并判断与否存在或重复。以便下面建立关系。
void Add(TSBNode *&b)//文献(夹)添加 #### 3 文献增长 ####
{
system("cls");
printf(" ********欢迎来到添加文献(夹)信息界面!********\n");
printf("\n");
TSBNode *p[MAXCHILD],*q;
int childnum;
char name[MAX];
printf("请输入需要添加文献(夹)分区或文献夹名字:");
scanf("%s",&name);
if(geshi==0) //判断与否进行格式化,否则返回格式化界面
{
printf("请先进行格式化!\n");
system("pause"); //按回车键继续;
areaTSBNode(b);
return;
}
q=FindNode(b,name);
while(q==NULL)
{
printf("不存在此分区或文献夹,请重新输入:"); //判断与否存在
scanf("%s",&name);
q=FindNode(b,name);
}
printf("请输入文献(夹)数目:");
scanf("%d",&childnum);
for(int i=1;i<=childnum;i++)
{
p[i]=(TSBNode *)malloc(sizeof(TSBNode));
p[i]->child=p[i]->brother=NULL;
printf("请输入第%d个文献(夹)信息:\n",i);
printf("名字:");
scanf("%s",&p[i]->data.name);
printf("大小:");
scanf("%s",&p[i]->data.volume);
if(FindNode(b,p[i]->data.name)!=NULL) //判断与否重复
{
printf("此文献夹已添加,请重新输入!\n");
printf("名字:\n");
scanf("%s",&p[i]->data.name);
printf("大小:");
scanf("%s",&p[i]->data.volume);
}
if(i==1)
q->child=p[i];
else
p[i-1]->brother=p[i];
}
printf("添加成功!\n");
system("pause");
}
文献(夹)修改中:前面写了查询结点函数,此中输入需要修改文献(夹)名字,查找到后直接修改信息。
void Change(TSBNode *b)//文献(夹)修改 #### 4 文献修改 ####
{
system("cls");
printf(" ********欢迎来到修改文献(夹)信息界面!********\n");
printf("\n");
TSBNode *q;
char name[MAX];
printf("请输入需要修改文献(夹)名字:");
scanf("%s",&name);
q=FindNode(b,name);
if(q==NULL)
{
printf("此文献(夹)不存在!\n");
system("pause");
return;
}
printf("请输入修改后文献(夹)信息:\n");
printf("名字:");
scanf("%s",&q->data.name);
printf("大小:");
scanf("%s",&q->data.volume);
system("pause");//按回车键继续
}
文献(夹)查询中:一方面查找到结点,判断与否存在,存在话直接输出此文献(夹)信息。下面输出途径中,要写查找父结点函数和结点高度函数。在查询中用for循环(用高度作为判断条件)将每个需要父节点输入到数组里,结束后,倒序输出。
int TSBHeight(TSBNode *b,TSBNode *q) //计算成员文献夹高度
{ static int h=0;
static int n=1;
if(b==NULL)
return h;
if(strcmp(b->data.name,q->data.name)==0)
return (h=n);
n++;
TSBHeight(b->child,q);
n--;
TSBHeight(b->brother,q);
return h;
}
TSBNode *FindFather(TSBNode *b,TSBNode *q)//查找某结点爸爸结点
{
TSBNode *p;
if(b!=NULL)
{
p=b->child;
while (p!=NULL)
{
if (p==q)
return b;
else
p=p->brother;
}
p=FindFather(b->child,q);
if(p!=NULL)
return p;
else
return FindFather(b->brother,q);
}
return 0;
}
void Path(TSBNode *b,TSBNode *q) //输出文献(夹)途径
{
TSBNode *p;
p=q;
if(TSBHeight(b,q)==0) printf("空文献!");
else
{
int h; //表达文献高度
h=TSBHeight(b,q);
for(int i=1;i<h;i++)
{
strcpy(b->date[i].name,FindFather(b,q)->data.name);
q=FindFather(b,q);
}
printf("途径为:");
for(i=h-1;i>=1;i--)
{
printf("%s-->",b->date[i].name);
}
printf("%s",p->data.name);printf("\n");
}
}
void Display(TSBNode *b,TSBNode *q) //输出文献夹信息和途径
{
printf("名字:%s 大小:%s\n",q->data.name,q->data.volume);
Path(b,q);
}
void Search(TSBNode *b)//文献(夹)查询 #### 5 文献查询 ####
{
system("cls");
printf(" ********欢迎来到查询文献(夹)信息界面!********\n");
printf("\n");
TSBNode *q;
char name[MAX];
printf("请输入你要查询文献(夹)名字:");
scanf("%s",&name);
q=FindNode(b,name);
if(q==NULL)
{
printf("不存在此文献(夹)!\n");
system("pause");
return;
}
Display(b,q);
system("pause");
}
文献(夹)删除中:一方面写删除子文献函数和查找前驱函数。在删除文献(夹)中一方面输入需要删除文献(夹)名字,判断与否存在,存在话,用p->brother和p->child同步为空和其中一种为空和都不为空四个条件来判断,删除子文献和查找前驱在里面调用,和相应递归来实现。删除了此文献,也删除了其子文献。
void DelTSBNode(TSBNode *b) //删除子文献
{
if(b->brother==NULL&&b->child==NULL)
{
free(b);
}
else
{
if(b->brother!=NULL)
{
DelTSBNode(b->brother);
}
if(b->child!=NULL)
{
DelTSBNode(b->child);
}
}
}
TSBNode * TSBFront(TSBNode *&b,char *name) //查找前驱结点
{
if(b->brother!=NULL && b->child==NULL)
{
if(strcmp(b->brother->data.name,name))
return TSBFront(b->brother,name);
else
return b;
}
if(b->child!=NULL && b->brother==NULL)
{
if(strcmp(b->child->data.name,name))
return TSBFront(b->child,name);
else
return b;
}
if(b->child!=NULL && b->brother!=NULL)
{ if(strcmp(b->child->data.name,name)==0||strcmp(b->brother->data.name,name)==0)
{
return b;
}
else
{
if(TSBFront(b->brother,name)==NULL)
return TSBFront(b->child,name);
else
return TSBFront(b->brother,name);
}
}
if(b->brother==NULL&&b->child==NULL)
return NULL;
}
void Delete(TSBNode *b) //电脑文献删除
{
system("cls");
printf(" ********欢迎来到删除文献(夹)信息界面!********\n");
printf("\n");
char name[MAX];
printf("请输入你要删除文献(夹)名字(其子文(件)将一并删除):");
scanf("%s",name);
TSBNode *p=FindNode(b,name);
if(p==NULL)
printf("无此文献(夹)!\n");
else
{
if(p==b)
{
if(p->child!=NULL)
DelTSBNode(p->child);
}
else
{
TSBNode *q=TSBFront(b,name);
if(p->brother==NULL)
{
if(q->child==p)
{
q->child=NULL;
if(p->child!=NULL)
DelTSBNode(p->child);
free(p);
}
else
{
q->brother=NULL;
if(p->child!=NULL)
DelTSBNode(p->child);
free(p);
}
}
else
{
if(q->child==p)
{
q->child=p->brother;
if(p->child!=NULL)
DelTSBNode(p->child);
free(p);
}
else
{
q->brother=p->brother;
if(p->child!=NULL)
DelTSBNode(p->child);
free(p);
}
}
主函数
硬盘初始化
文献(夹)查询
硬盘格式化
文献(夹)修改
文献(夹)添加
文献(夹)删除
P=q
重复!
继续!
P=q
P=q
P=q
重输!
继续!
继续!
重输!
继续!
重输!
退出!
}printf(" 删除成功!\n");
}
system("pause");
}
流程图:
Yes no yes no yes no yes no
符号阐明:char name[MAX];char type[MAX];char volume[MAX];文献夹信息
int chushi=0,geshi=0;定义全局变量,分别用在格式化和添加文献函数中,判断初始化和格式化与否进行,是话继续,否则返回相应界面
struct tnode *brother;指向兄弟struct tnode *child;指向孩子
ElemType data;结点值ElemType date[MAX];定义数组,用于途径中父节点存储,最后输出 #include <stdlib.h>头文献 system("cls");达到清屏效果
四、运营示例及成果分析
主函数,最初界面
图1
初始化界面:
图2
格式化界面:
图3
另一种状况,主盘名字不存在:
图4
添加文献夹界面:
图5
添加信息时,文献重复状况:
图6
在文献夹里添加文献(夹):
图7
修改界面:
图8
修改另一种状况,不存在:
图9
查询界面:
图10
删除界面:
图11
删除后进行查询效果,1子孩子也被删除了,界面:
图12
1兄弟还存在,不受影响界面:
图13
退出结束界面:
图14
五、调试和运营程序过程中产生问题及采用办法
1、在主菜单中如果直接进行3添加信息,就会直接结束,由于必要先把1初始化和2格式化做好。因此就设了两个全局变量int chushi=0,geshi=0;分别放在格式化和添加函数中进行判断。例如:
if(chushi==0) //判断与否进行初始化,否则返回初始化界面
{
printf("请先进行硬盘初始化!\n");
system("pause"); //按回车键继续;
CreateBTNode(b);
return;
}
2、 在删除里面,一方面建立前驱函数,和查找中建立父节点函数,刚开始写找不到,直接结束,越看越乱,日后就画一种树,指定结点去顺,就很容易发现漏条件状况,再添加进去就好了。
3、 在输出途径中,就是想从根节点进行往下找,但是函数总是实现不了,并且思路很复杂,有太多状况浮现。日后就倒着找,调用父节点函数,一种一种输出。但始终是倒序输出状况。就定义了一种数组date[max],查找到就输进去,然后依照高度作为条件用for循环倒着将数组输出。就变成我想要正序了。
for(i=h-1;i>=1;i--)
{
printf("%s-->",b->date[i].name);
}
printf("%s",p->data.name);printf("\n");
4、接下来就是好多小错误,例如return;在if中和函数中放位置有误,导致直接结束,没有进行下一步。尚有函数定义void Display(TSBNode *b,TSBNode *q)中TSBNode *b未定义,浮现错误。下面调用此函数中,少写了变量和错写,就会浮现好多错误,但很容易找到和修改。printf("%s-->",b->date[i].name);里多加了&取地址,浮现问题。尚有某些判断函数(与否存在和与否重复)位置放得不对,就没进行此判断等等。但总体这些都容易解决。
六、总结
第一天看到这个题目时,电脑存储构造设计与实现(树,查找)。需要用树,脑子里就立即显示一张图。
我电脑
C:
D:
E:
etc
WINDOWS
Program Files
Picture
Music
……
……
……
……
……
……
……
……
这个不同于我很熟悉二叉树状况。它一种结点就有好多子结点,而不是二叉树两个。我就立即翻书看,但对于树简介少之又少。刚开始有点头疼,如何建立关系,又如何查询哪?日后回去查书找树知识,但大篇幅还是二叉树。我就找了某些家谱系统看了一下,明白了树建立,修改,删除,查询思想后。便开始着手写我程序了。一方面用孩子兄弟链为主思想。就像二叉树左右孩子同样。
中间写时候,先写了主干,必定有诸多局限性和没有考虑到东西。日后就一点一点加进去。像增长中,加入了判断与否重复代码。查询中,增长了与否存在和与否重复代码,删除、修改中增长了与否存在判断代码。尚有判断与否初始化和格式化状况,添加了全局变量。在运营调试中看输出格式与否好看,就在代码中在恰当位置加入换行,或者主菜单对齐等等。这样整个程序就更加完美了。
要说收获,必定诸多。不论是在知识丰富和巩固,还是在做事谨慎和耐心上,都让我受益匪浅。我做是树内容,在之前都是很理解二叉树,当前对树有关知识点和算法实现都很是熟悉了。完毕之后感觉,感觉不是会了一种课程设计,好多管理系统(用树知识)都会了,所有这些都大同小异。在编写过程中会浮现某些很难看出来错误,这时就锻炼了我耐心,一步一步地找,切忌暴躁。在接下来地编写中就很谨慎,以防很小知识点导致错误,耽误更多时间。
七、参照文献
[1] 李春葆等著.数据构造教程(第三版).清华大学出版社,
[2] 滕国文著.数据构造课程设计.清华大学出版社,.9
展开阅读全文