电脑的存储结构设计与实现.docx
《电脑的存储结构设计与实现.docx》由会员分享,可在线阅读,更多相关《电脑的存储结构设计与实现.docx(28页珍藏版)》请在冰点文库上搜索。
电脑的存储结构设计与实现
一、课题名称
电脑存储结构设计与实现(树,查找)
二、主要容
电脑存储结构设计与实现主要是模拟“我的电脑”中硬盘信息的建立、查找、插入、修改、删除等功能。
可。
基本功能如下:
(1)硬盘初始化信息:
我的电脑(根结点)。
(2)硬盘格式化:
为我的电脑分区,分区的个数由后台终端输入决定,每个硬盘分区信息包括卷名、文件系统类型、容量等。
(3)文件或文件夹的添加:
即创建某个分区的孩子结点信息(文件(夹)),孩子结点的数目由控制台端给出,信息包括文件(夹)名,文件(夹)大小,所有文件(夹)的文件名此处不能重复。
创建好的文件夹中还能创建其孩子结点信息(文件(夹))。
(4)文件或文件夹信息的修改:
可以修改某一文件或文件夹的信息,包括名字和大小。
(5)文件或文件夹的查询:
查询某一文件或文件夹的具体路径。
(从我的电脑开始)
(6)文件或文件夹的删除:
删除此文件,如果是文件夹,若其有后代,将删除其所有后代成员(文件或文件夹)。
三、课题设计的基本思想,原理和算法描述
此课题主要用树来建立电脑的存储结构设计,并用树的相关知识,递归的思想贯穿始终,实现硬盘的初始化和格式化,并在分区里实现文件(夹)的添加、修改、查询、删除的功能。
主函数和总界面:
voidmenu()
{
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("请选择功能操作号:
");//选择相应数字实现对应功能项
}
voidmain()
{
TSBNode*b;
while
(1)
{
menu();
intc;
scanf("%d",&c);
switch(c)
{
case1:
CreateBTNode(b);break;
case2:
areaTSBNode(b);break;
case3:
Add(b);break;
case4:
Change(b);break;
case5:
Search(b);break;
case6:
Delete(b);break;
case7:
return;
default:
printf("选择有误,请重新选择!
\n");
}
}
}
硬盘初始化中:
直接输入主盘的名字,并将此名字赋给根节点。
voidCreateBTNode(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循环里,对每个分区和根节点建立关系。
voidareaTSBNode(TSBNode*&b)//硬盘格式化####2格式化####
{
system("cls");
printf("********欢迎来到硬盘格式化信息界面!
********\n");
printf("\n");
TSBNode*p[MAXCHILD];
charname[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);
}
intchildnum;//定义分区数目
printf("请输入分区的数目:
");
scanf("%d",&childnum);
for(inti=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");//按回车键继续;
}
文件(夹)的添加中:
同格式化,首先输入分区或文件(夹)的名字,判断是否存在此分区或文件(夹),同时也判断是否进行硬盘格式化,是的话继续,否则返回格式化的界面。
还增加了需要添加文件的输入,并判断是否存在或重复。
方便下面的建立关系。
voidAdd(TSBNode*&b)//文件(夹)的添加####3文件增加####
{
system("cls");
printf("********欢迎来到添加文件(夹)的信息界面!
********\n");
printf("\n");
TSBNode*p[MAXCHILD],*q;
intchildnum;
charname[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(inti=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");
}
文件(夹)的修改中:
前面写了查询结点的函数,此中输入需要修改的文件(夹)的名字,查找到后直接修改信息。
voidChange(TSBNode*b)//文件(夹)的修改####4文件修改####
{
system("cls");
printf("********欢迎来到修改文件(夹)的信息界面!
********\n");
printf("\n");
TSBNode*q;
charname[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循环(用高度作为判断条件)将每个需要的父节点输入到数组里,结束后,倒序输出。
intTSBHeight(TSBNode*b,TSBNode*q)//计算成员的文件夹的高度
{staticinth=0;
staticintn=1;
if(b==NULL)
returnh;
if(strcmp(b->data.name,q->data.name)==0)
return(h=n);
n++;
TSBHeight(b->child,q);
n--;
TSBHeight(b->brother,q);
returnh;
}
TSBNode*FindFather(TSBNode*b,TSBNode*q)//查找某结点的父亲结点
{
TSBNode*p;
if(b!
=NULL)
{
p=b->child;
while(p!
=NULL)
{
if(p==q)
returnb;
else
p=p->brother;
}
p=FindFather(b->child,q);
if(p!
=NULL)
returnp;
else
returnFindFather(b->brother,q);
}
return0;
}
voidPath(TSBNode*b,TSBNode*q)//输出文件(夹)路径
{
TSBNode*p;
p=q;
if(TSBHeight(b,q)==0)printf("空文件!
");
else
{
inth;//表示文件的高度
h=TSBHeight(b,q);
for(inti=1;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");
}
}
voidDisplay(TSBNode*b,TSBNode*q)//输出文件夹信息和路径
{
printf("名字:
%s大小:
%s\n",q->data.name,q->data.volume);
Path(b,q);
}
voidSearch(TSBNode*b)//文件(夹)的查询####5文件查询####
{
system("cls");
printf("********欢迎来到查询文件(夹)信息界面!
********\n");
printf("\n");
TSBNode*q;
charname[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同时为空和其中一个为空和都不为空四个条件来判断,删除子文件和查找前驱在里面调用,和相应的递归来实现。
删除了此文件,也删除了其子文件。
voidDelTSBNode(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))
returnTSBFront(b->brother,name);
else
returnb;
}
if(b->child!
=NULL&&b->brother==NULL)
{
if(strcmp(b->child->data.name,name))
returnTSBFront(b->child,name);
else
returnb;
}
if(b->child!
=NULL&&b->brother!
=NULL)
{if(strcmp(b->child->data.name,name)==0||strcmp(b->brother->data.name,name)==0)
{
returnb;
}
else
{
if(TSBFront(b->brother,name)==NULL)
returnTSBFront(b->child,name);
else
returnTSBFront(b->brother,name);
}
}
if(b->brother==NULL&&b->child==NULL)
returnNULL;
}
voidDelete(TSBNode*b)//电脑文件删除
{
system("cls");
printf("********欢迎来到删除文件(夹)信息界面!
********\n");
printf("\n");
charname[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);
}
}
}printf("删除成功!
\n");
}
system("pause");
}
流程图:
Yesnoyesnoyesnoyesno
符号说明:
charname[MAX];chartype[MAX];charvolume[MAX];文件夹的信息
intchushi=0,geshi=0;定义的全局变量,分别用在格式化和添加文件的函数中,判断初始化和格式化是否进行,是的话继续,否则返回相应界面
structtnode*brother;指向兄弟structtnode*child;指向孩子
ElemTypedata;结点的值ElemTypedate[MAX];定义数组,用于路径中父节点的存储,最后输出#include头文件system("cls");达到清屏的效果
四、运行示例及结果分析
主函数,最初的界面
图1
初始化界面:
图2
格式化界面:
图3
另一种情况,主盘名字不存在:
图4
添加文件夹界面:
图5
添加信息时,文件重复的情况:
图6
在文件夹里添加文件(夹):
图7
修改界面:
图8
修改的另一种情况,不存在:
图9
查询界面:
图10
删除界面:
图11
删除后进行查询的效果,1的子孩子也被删除了,界面:
图12
1的兄弟还存在,不受影响的界面:
图13
退出结束的界面:
图14
五、调试和运行程序过程中产生的问题及采取的措施
1、在主菜单中如果直接进行3添加的信息,就会直接结束,因为必须先把1初始化和2格式化做好。
所以就设了两个全局变量intchushi=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中和函数中放的位置有误,导致直接结束,没有进行下一步。
还有函数定义voidDisplay(TSBNode*b,TSBNode*q)中TSBNode*b未定义,出现错误。
下面调用此函数中,少写了变量和