主要思路:
1.定义结构体node,包含1)名字name(2)指向下级目录指针ctl(3)指向下级文件指针file(4)指向同级目录或文件指针next(取决于它本身是目录还是文件)。
定义一个全局的指针ptr,指向上一个处理完毕的结点,比如一开始在输入“ac”的中,ptr一开始指向root,从root开始处理a,处理完后ptr指向a,然后从ptr(即a)开始处理b,处理完后ptr指向b,再从ptr(即b)开始处理c。
2.处理一行数据时,字符串后带的为目录,否则为文件。
3.假设插入一个目录类型结点s,从某一结点(设为x)开始,如果x的目录为空,直接插入;如果不为空,从x的指向的目录a开始,s与a比较,如果小于(按字典序排在前面),则在x和a之间插入s即可,否则,s继续跟a的next结点b比较,如果s小于b了,则在a与b之间插入s,以此类推……如果到链表遍历完毕都没有找到比s大的结点,说明s最大,需要放在最后,在遍历结束后直接让链表最后一个结点指向s即可。在s插入完毕后,ptr指向s,表明下一个结点的处理是从ptr结点开始的,如本段开头s的插入是从x结点开始的。
如果s跟x的目录重名了,则不需要插入s,直接令ptr指向x即可,然后开始下一个结点的处理(那就是从x,即ptr开始处理了)。
4.假设插入一个文件类型结点s,方法与上述插入目录结点时类似,只是插入文件结点时,是小于(即按字典序规则排在前面),等于(即重名)的时候插入,因为当
文件重名时,不能说只有一个文件,有n个文件重名那就是有n个文件,所以s仍然需要插入,这里跟目录的插入不同,重名的目录即使有多个也是只看成一个的,所以不需要重复插入了。
5.还要注意,在a和c之间插入b时,需要分情况处理,如果a与b同级,是a的next指向b;如果a比高一级,则a的ctl或者file指针指向b。
6.使用Print()函数递归输出
1 void Print(int cnt, struct node* p) 2 { 3 struct node* s = p; 4 if (!p)return; 5 print_sp(cnt); 6 cnt += 2; 7 cout << p->name << endl; 8 while (s->ctl)//输出完目录 9 { 10 Print(cnt, s->ctl); 11 s->ctl = s->ctl->next; 12 } 13 while (p->file)//再输出文件 14 { 15 Print(cnt, p->file); 16 p->file = p->file->next; 17 } 18 }
1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 5 using namespace std; 6 typedef struct node//文件或目录的结点 7 { 8 char name[300]; 9 struct node* ctl;//指向下一级的目录 10 struct node* file;//指向下一级的文件 11 struct node* next;//指向同级的文件或目录 12 }; 13 struct node root;//定义根节点为全局变量 14 struct node* ptr = NULL;//定义一个全局的指向node的指针 15 //ptr的作用:每次插入结点后,(针对同一行的结点)ptr指向新插入的结点,使得下一次插入的时候能直接从ptr开始处理 16 //如果没有新插入结点(只有一种情况,即有同名目录的时候,ptr直接指向同名的那个结点,然后直接退出插入函数 17 //当处理完一行数据的时候,ptr指向root,因为每一行都是从root开始处理的 18 bool smaller(char s1[], char s2[])//按照字典序规则比较两个字符串,s1<s2返回true 19 { 20 for (int i = 0; i < 300; i++) 21 { 22 if (s1[i] == s2[i]) 23 { 24 for (int j = i; j < 300; j++) 25 { 26 if (s1[j] == '