树的遍历:文件目录结构的显示
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
Tree* temp = this;
/*** 如果当前的结点没有孩子结点,则它的Size值不变,即为输入时候的值 ***/
if(temp->FirstChild != 0){
temp = temp->FirstChild;
while(temp != 0){
temp->reSize();
Size += temp->Size;
(aa.txt 12)
*/usr 1
()
表示含有两个不同的根目录,目录名都是/usr,第一个根目录/usr下包含mark和alex两个子目录,mark目录下包含大小为3的文件hw.c和子目录course,alex目录下有一个大小为5的文件hw.c,子目录course下包含文件aa.txt,其大小为12;第二个根目录/usr下为空。
2.2
输入数据中对目录大小的初始值一般为1,而目录的真正大小应该是自身的大小和它包含的所有文件及子目录的大小之和。因此,在计算目录大小的时候,需要遍历它下面所有的文件和子目录,可以采用递归嵌套的后序遍历方式。另外要注意,采用孩子兄弟双亲链表表示时,父目录下的所有子目录和子文件都在该父目录的左子树上(右子树第一个节点是该目录的兄弟节点),所以白努力的时候只需要遍历目录对的左子树即可。
数Hale Waihona Puke Baidu结构课程设计报告
树的遍历:文件目录结构的显示
专业
计算机科学与技术
学生姓名
****
班级
计算机***
学号
*****
指导教师
徐燕萍
完成日期
2014年7月4日
树的遍历:文件目录结构的显示
1
给出Unix下目录和文件信息,要求编程实现将其排列成一定缩进的树。具体要求如下。
输入要求:
输入数据包含几个测试方案。每一个案例由几行组成,每一行都代表了目录树的层次结构。第一行代表目录的根节点。若是目录节点,那么它的孩子节点将在第二行中被列出,同时用一对圆括号“()”界定。同样,如果这些孩子节点钟某一个也是目录的话,那么这个目录所包含的内容将在随后的一行中列出,有一对圆括号将首位界定。目录的输入格式为:*name size,文件的输入格式为:name size,其中*代表当前节点的目录,name代表文件或目录的名称,由一串长度不大于10的字符组成,并且name字符串中不能包含有‘(’,‘)’,‘[’,‘]’,‘*’。size是该文件/目录的大小,为大于0的整数。每一个案例中最多只能包含10层,每一层最多有10个文件/目录。
int i;
outfile.open("output.txt",ios::app);
if(!outfile){
cout<<"cannot append the output file.\n";
exit(0);
}
if(!checkName(Name)){
cout<<"input error!--"<<Name<<endl;
temp = temp->NextSibling;
}
}
}
/***检查Name中有无非法字符**************/
bool checkName(string s)
{
if(s[0]!='*' && s.length() > 10)
return false;
if(s[0]=='*' && s.length() > 11)
Tree* parent; /* 指向双亲结点 */
public:
Tree(string Name = "", int Size = 0);/* 构造函数 */
void parse(); /* 根据输入数据来建立树形结构 */
void reSize(); /* 重新统计树结点的大小 */
void outPut();/* 输出树形结构 */
return false;
if(s[0]!='*' && (s[0]=='(' || s[0]==')' || s[0]=='[' || s[0]==']'))
return false;
for(int i=1;i<s.length();i++){
if(s[i]=='*' || s[i]=='(' || s[i]==')' || s[i]=='[' || s[i]==']')
temp = FirstChild;
while(temp != NULL)
{
temp1 = temp;
temp = temp->NextSibling;
delete temp1;
}
}
/* 先序遍历根结点下的所有结点,将每一个结点的Size值都加到根结点的Size中去**/
void Tree::reSize()
3
利用visual c++,新建一个c++文件,将以下代码输入。
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
string s = "";
int startPos = 0;
ofstream outfile;
2.
输出是一个先序遍历的过程。为完成对树形的输出,兄弟目录之间需要相同的缩进,用‘|’上下相连,而父子目录或父目录和子文件之间需要设定正确的缩进,子目录或子文件要比父目录向右缩进8个空格。设置一个标志数组flag[11](每个目录下最大的层次数为10),当前Tree*temp指针所指的节点如果有兄弟节点,则置flag数组值为1,否则置为0;并由此节点反复查询它的祖先节点的情况,直到根节点为止。输出时,遇到flag[]=1时,屏幕输出“| ”,表明是兄弟节点;遇到flag[]=0则输出“ ”, 有相同的缩进,而子节点总比父节点向右缩进8个空格。
return false;
}
return true;
}
/*** 按照先序遍历的方式有缩进地来输出树形结构 ***/
void Tree::outPut()
{
Tree* temp; /*用来指向当前结点的祖先结点*/
Tree* temp1;
bool flag[11];/*用来标志输出缩进、层次情况的数组*/
flag[i++] = true;
else
flag[i++] = false;
}
/*兄弟结点之间有相同的缩进,子结点比父结点向右缩进8个空格*/
while(i--)
{
if(flag[i] == true)
outfile<<"| ";
else
outfile<<" ";
}
outfile.close();
if(i>=10){
//检查当前的父目录包含的子文件(或目录数)是否大于10;
cout<<"input error!--dictionary contains more than 10 levels."<<endl;
exit(0);
}
temp = temp->parent;
if(temp->NextSibling != NULL)
if(!outfile){
cout<<"cannot append the output file.\n";
exit(0);
}
i = 0;
temp = temp1;
while(temp->parent != NULL)
{
/*当前temp指针所指的结点如果有兄弟结点,则置flag数组值为1,否则置为0;并由此结点反复查询它的祖先结点的情况,直到根结点为止*/
temp1->outPut();
temp1 = temp1->NextSibling;
}
}
/*** 跳过字符串s中,第(*i)个之后多余的空格 ***/
void skipWhiteSpace(string& s, int* i)
{
while(s[*i] == '\t' || s[*i] == ' ')
exit(0);
}
outfile<<"|_"<<Name<<"["<<Size<<"]\n";
outfile.close();
/* 输出当前的结点信息 */
temp1= FirstChild;/* 用来指向当前结点的子结点 */
while(temp1 != NULL)
{
outfile.open("output.txt",ios::app);
2.1
根据输入来确定树形关系时,首先读取根节点目录/文件名和大小值,并根据这些信息建立一个新的节点;然后读入后面各行信息,对于同一括号中的内容,即具有相同父节点的那些节点建立兄弟关联。这个函数实际上是采取遍历建立树形链表结构。
定义一个Tree*类型的数组treeArray[],用来存放目录的节点信息,并定义两个整型变量head和rear,head值用来标记当前节点的父节点位置,每处理完一对括号,head需要增加1,即下一对待处理括号的父节点在treeArray[]中要往后移一个位置。如果当前处理的节点是目录类型,则将它放在treeArray[]数组中,rear是treeArray[]的下标变量,加入一个目录节点信息,rear就增加1;如果是文件类型的目录,则需要按照Name和Size建立一个树的节点,并和head所指的父节点建立关联,但是不用放入treeArray[]中。
输出要求:
对每一个测试案例,输出时要求:第d层的文件/目录名前面需要插入8*d个空格,兄弟节点之间要在同一列上。不要使用Tab(制表符)来统一输出的缩进。每一个目录的大小(size)是它包含的所有子目录和文件大小以及它自身大小的总和。
输入例子:
*/usr1
(*mark 1 *alex 1)
(hw.c3 *course 1)(hw.c 5)
2.4消除输入中多余空格的函数skipWhiteSpace(string &s,int *i)
从用户输入数据中读入一行后,调用该函数来跳过s字符串中s[i]之后的空格,以方便后面的处理。
此外,关于读入目录名称、大小,以及将string类型的Size值转换成int类型的函数的实现,相对比较简单,此处不再赘述。
输出例子:
|_*usr[24]
|_*mark[17]
| |_hw.c[3]
| |_*course[13]
| |_aa.txt[12]
|_*alex[6]
|_hw.c[5]
|_*/usr[1]
2
目录结构是一种典型的树形结构,为了方便对目录的查找、遍历等操作,可以选择孩子兄弟双亲链表来存储树的结构。程序中要求对目录的大小进行重新计算,根据用户的输入来建立相应的孩子兄弟双亲链表,最后输出树形结构。可以引用一个Tree类,将树的构造、销毁、目录的大小重新计算(reSize)、建立树形链表结构(parse)、树形结构输出(outPut)等一系列操作都封装起来,同时对于每一个树的节点,它的私有变量除了名称(Name)、大小(Size)和层数(Depth)之外,根据孩子兄弟双亲链表表示的需要,还要设置三个指针,即父指针(Tree*parent)、下一个兄弟指针(Tree*NextSibling)和第一个孩子指针(Tree*FirstChild)。
this->Name = Name;
this->Size = Size;
FirstChild = NULL;
NextSibling = NULL;
parent = NULL;
}
/*** 析构函数,删除同一根结点下的各个子结点,释放空间 ***/
Tree::~Tree()
{
Tree* temp;
Tree* temp1;
~Tree(); /* 析构函数 */
};
/*** 树结点数组treeArray[],以及用来标注双亲结点位置的head和目录结点的rear***/
Tree* treeArray[100];
int head = 0, rear = 0;
/*** 建立只有一个结点的树,其三个指针域均为空 ***/
Tree::Tree(string Name, int Size){
ifstream infile;
/**构造Tree类**/
class Tree{
string Name; /* 树的根结点名称 */
int Size; /* 树的大小,用于统计这棵树本身及其包含的所以子树大小的总和*/
Tree* FirstChild; /* 指向它的第一个孩子结点 */
Tree* NextSibling; /* 指向它的下一个兄弟结点 */
为进一步说明这个树形链表结构的构成,可参考图3-1。
treeArray[]
图3-1通过parse()构建的数据结构事例
它是根据如下的具体输入例子所形成的结构示意。
输入:
*/usr1
(*mark 1 *alex 1)
(hw.c3 *course 1)(hw.c 5)
(aa.txt 12)
形成的数据结构如图2.5所示。
Tree* temp = this;
/*** 如果当前的结点没有孩子结点,则它的Size值不变,即为输入时候的值 ***/
if(temp->FirstChild != 0){
temp = temp->FirstChild;
while(temp != 0){
temp->reSize();
Size += temp->Size;
(aa.txt 12)
*/usr 1
()
表示含有两个不同的根目录,目录名都是/usr,第一个根目录/usr下包含mark和alex两个子目录,mark目录下包含大小为3的文件hw.c和子目录course,alex目录下有一个大小为5的文件hw.c,子目录course下包含文件aa.txt,其大小为12;第二个根目录/usr下为空。
2.2
输入数据中对目录大小的初始值一般为1,而目录的真正大小应该是自身的大小和它包含的所有文件及子目录的大小之和。因此,在计算目录大小的时候,需要遍历它下面所有的文件和子目录,可以采用递归嵌套的后序遍历方式。另外要注意,采用孩子兄弟双亲链表表示时,父目录下的所有子目录和子文件都在该父目录的左子树上(右子树第一个节点是该目录的兄弟节点),所以白努力的时候只需要遍历目录对的左子树即可。
数Hale Waihona Puke Baidu结构课程设计报告
树的遍历:文件目录结构的显示
专业
计算机科学与技术
学生姓名
****
班级
计算机***
学号
*****
指导教师
徐燕萍
完成日期
2014年7月4日
树的遍历:文件目录结构的显示
1
给出Unix下目录和文件信息,要求编程实现将其排列成一定缩进的树。具体要求如下。
输入要求:
输入数据包含几个测试方案。每一个案例由几行组成,每一行都代表了目录树的层次结构。第一行代表目录的根节点。若是目录节点,那么它的孩子节点将在第二行中被列出,同时用一对圆括号“()”界定。同样,如果这些孩子节点钟某一个也是目录的话,那么这个目录所包含的内容将在随后的一行中列出,有一对圆括号将首位界定。目录的输入格式为:*name size,文件的输入格式为:name size,其中*代表当前节点的目录,name代表文件或目录的名称,由一串长度不大于10的字符组成,并且name字符串中不能包含有‘(’,‘)’,‘[’,‘]’,‘*’。size是该文件/目录的大小,为大于0的整数。每一个案例中最多只能包含10层,每一层最多有10个文件/目录。
int i;
outfile.open("output.txt",ios::app);
if(!outfile){
cout<<"cannot append the output file.\n";
exit(0);
}
if(!checkName(Name)){
cout<<"input error!--"<<Name<<endl;
temp = temp->NextSibling;
}
}
}
/***检查Name中有无非法字符**************/
bool checkName(string s)
{
if(s[0]!='*' && s.length() > 10)
return false;
if(s[0]=='*' && s.length() > 11)
Tree* parent; /* 指向双亲结点 */
public:
Tree(string Name = "", int Size = 0);/* 构造函数 */
void parse(); /* 根据输入数据来建立树形结构 */
void reSize(); /* 重新统计树结点的大小 */
void outPut();/* 输出树形结构 */
return false;
if(s[0]!='*' && (s[0]=='(' || s[0]==')' || s[0]=='[' || s[0]==']'))
return false;
for(int i=1;i<s.length();i++){
if(s[i]=='*' || s[i]=='(' || s[i]==')' || s[i]=='[' || s[i]==']')
temp = FirstChild;
while(temp != NULL)
{
temp1 = temp;
temp = temp->NextSibling;
delete temp1;
}
}
/* 先序遍历根结点下的所有结点,将每一个结点的Size值都加到根结点的Size中去**/
void Tree::reSize()
3
利用visual c++,新建一个c++文件,将以下代码输入。
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
string s = "";
int startPos = 0;
ofstream outfile;
2.
输出是一个先序遍历的过程。为完成对树形的输出,兄弟目录之间需要相同的缩进,用‘|’上下相连,而父子目录或父目录和子文件之间需要设定正确的缩进,子目录或子文件要比父目录向右缩进8个空格。设置一个标志数组flag[11](每个目录下最大的层次数为10),当前Tree*temp指针所指的节点如果有兄弟节点,则置flag数组值为1,否则置为0;并由此节点反复查询它的祖先节点的情况,直到根节点为止。输出时,遇到flag[]=1时,屏幕输出“| ”,表明是兄弟节点;遇到flag[]=0则输出“ ”, 有相同的缩进,而子节点总比父节点向右缩进8个空格。
return false;
}
return true;
}
/*** 按照先序遍历的方式有缩进地来输出树形结构 ***/
void Tree::outPut()
{
Tree* temp; /*用来指向当前结点的祖先结点*/
Tree* temp1;
bool flag[11];/*用来标志输出缩进、层次情况的数组*/
flag[i++] = true;
else
flag[i++] = false;
}
/*兄弟结点之间有相同的缩进,子结点比父结点向右缩进8个空格*/
while(i--)
{
if(flag[i] == true)
outfile<<"| ";
else
outfile<<" ";
}
outfile.close();
if(i>=10){
//检查当前的父目录包含的子文件(或目录数)是否大于10;
cout<<"input error!--dictionary contains more than 10 levels."<<endl;
exit(0);
}
temp = temp->parent;
if(temp->NextSibling != NULL)
if(!outfile){
cout<<"cannot append the output file.\n";
exit(0);
}
i = 0;
temp = temp1;
while(temp->parent != NULL)
{
/*当前temp指针所指的结点如果有兄弟结点,则置flag数组值为1,否则置为0;并由此结点反复查询它的祖先结点的情况,直到根结点为止*/
temp1->outPut();
temp1 = temp1->NextSibling;
}
}
/*** 跳过字符串s中,第(*i)个之后多余的空格 ***/
void skipWhiteSpace(string& s, int* i)
{
while(s[*i] == '\t' || s[*i] == ' ')
exit(0);
}
outfile<<"|_"<<Name<<"["<<Size<<"]\n";
outfile.close();
/* 输出当前的结点信息 */
temp1= FirstChild;/* 用来指向当前结点的子结点 */
while(temp1 != NULL)
{
outfile.open("output.txt",ios::app);
2.1
根据输入来确定树形关系时,首先读取根节点目录/文件名和大小值,并根据这些信息建立一个新的节点;然后读入后面各行信息,对于同一括号中的内容,即具有相同父节点的那些节点建立兄弟关联。这个函数实际上是采取遍历建立树形链表结构。
定义一个Tree*类型的数组treeArray[],用来存放目录的节点信息,并定义两个整型变量head和rear,head值用来标记当前节点的父节点位置,每处理完一对括号,head需要增加1,即下一对待处理括号的父节点在treeArray[]中要往后移一个位置。如果当前处理的节点是目录类型,则将它放在treeArray[]数组中,rear是treeArray[]的下标变量,加入一个目录节点信息,rear就增加1;如果是文件类型的目录,则需要按照Name和Size建立一个树的节点,并和head所指的父节点建立关联,但是不用放入treeArray[]中。
输出要求:
对每一个测试案例,输出时要求:第d层的文件/目录名前面需要插入8*d个空格,兄弟节点之间要在同一列上。不要使用Tab(制表符)来统一输出的缩进。每一个目录的大小(size)是它包含的所有子目录和文件大小以及它自身大小的总和。
输入例子:
*/usr1
(*mark 1 *alex 1)
(hw.c3 *course 1)(hw.c 5)
2.4消除输入中多余空格的函数skipWhiteSpace(string &s,int *i)
从用户输入数据中读入一行后,调用该函数来跳过s字符串中s[i]之后的空格,以方便后面的处理。
此外,关于读入目录名称、大小,以及将string类型的Size值转换成int类型的函数的实现,相对比较简单,此处不再赘述。
输出例子:
|_*usr[24]
|_*mark[17]
| |_hw.c[3]
| |_*course[13]
| |_aa.txt[12]
|_*alex[6]
|_hw.c[5]
|_*/usr[1]
2
目录结构是一种典型的树形结构,为了方便对目录的查找、遍历等操作,可以选择孩子兄弟双亲链表来存储树的结构。程序中要求对目录的大小进行重新计算,根据用户的输入来建立相应的孩子兄弟双亲链表,最后输出树形结构。可以引用一个Tree类,将树的构造、销毁、目录的大小重新计算(reSize)、建立树形链表结构(parse)、树形结构输出(outPut)等一系列操作都封装起来,同时对于每一个树的节点,它的私有变量除了名称(Name)、大小(Size)和层数(Depth)之外,根据孩子兄弟双亲链表表示的需要,还要设置三个指针,即父指针(Tree*parent)、下一个兄弟指针(Tree*NextSibling)和第一个孩子指针(Tree*FirstChild)。
this->Name = Name;
this->Size = Size;
FirstChild = NULL;
NextSibling = NULL;
parent = NULL;
}
/*** 析构函数,删除同一根结点下的各个子结点,释放空间 ***/
Tree::~Tree()
{
Tree* temp;
Tree* temp1;
~Tree(); /* 析构函数 */
};
/*** 树结点数组treeArray[],以及用来标注双亲结点位置的head和目录结点的rear***/
Tree* treeArray[100];
int head = 0, rear = 0;
/*** 建立只有一个结点的树,其三个指针域均为空 ***/
Tree::Tree(string Name, int Size){
ifstream infile;
/**构造Tree类**/
class Tree{
string Name; /* 树的根结点名称 */
int Size; /* 树的大小,用于统计这棵树本身及其包含的所以子树大小的总和*/
Tree* FirstChild; /* 指向它的第一个孩子结点 */
Tree* NextSibling; /* 指向它的下一个兄弟结点 */
为进一步说明这个树形链表结构的构成,可参考图3-1。
treeArray[]
图3-1通过parse()构建的数据结构事例
它是根据如下的具体输入例子所形成的结构示意。
输入:
*/usr1
(*mark 1 *alex 1)
(hw.c3 *course 1)(hw.c 5)
(aa.txt 12)
形成的数据结构如图2.5所示。