7-30 目录树 (30分)

主要思路:

1.定义结构体node,包含1)名字name(2)指向下级目录指针ctl(3)指向下级文件指针file(4)指向同级目录或文件指针next(取决于它本身是目录还是文件)。

定义一个全局的指针ptr,指向上一个处理完毕的结点,比如一开始在输入“a\b\c”的中,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] == ‘\0‘ && s2[j] != ‘\0‘)
 27                 {
 28                     return true;
 29                 }
 30                 if (s1[j] != ‘\0‘ && s2[j] == ‘\0‘)
 31                 {
 32                     return false;
 33                 }
 34                 if (s1[j] < s2[j])
 35                 {
 36                     return true;
 37                 }
 38                 else if (s1[j] > s2[j])
 39                 {
 40                     return false;
 41                 }
 42             }
 43         }
 44         else if (s1[i] < s2[i])return true;
 45         else return false;
 46     }
 47 }
 48 bool equal(char s1[], char s2[])//比较两个字符串,相等即返回true
 49 {
 50     for (int i = 0; i < 300; i++)
 51     {
 52         if (s1[i] != s2[i])
 53         {
 54             return false;
 55         }
 56     }
 57     return true;
 58 }
 59 void ins_file(char name[])//插入一个文件结点
 60 {
 61     struct node* s = new struct node;
 62     s->ctl = s->file = s->next = NULL;
 63     strcpy(s->name, name);
 64     if (!ptr->file)
 65     {
 66         ptr->file = s;
 67     }
 68     else
 69     {//遍历文件结点,将s插入到第一个比它大的结点中(字典序排序规则)
 70         struct node* p = ptr->file;//初始化为ptr的file指向的结点
 71         struct node* p_pio = ptr;//前驱结点
 72         int flag = 0;//标志,没有插入,置0;插入了s结点,置1
 73         while (p)
 74         {//重名的文件也要当成两个文件,但是重名目录不需要
 75             if (smaller(s->name, p->name) || equal(s->name, p->name))//如果小于或等于,就可以头插入
 76             {
 77                 flag = 1;
 78                 s->next = p;
 79                 if (p_pio->file == p)//如果上一个结点是上级结点
 80                     p_pio->file = s;//则令上一个结点的file指向s
 81                 else
 82                     p_pio->next = s;//如果是同级结点,则令它的next指向s
 83                 break;
 84             }
 85             p_pio = p;//
 86             p = p->next;
 87         }
 88         if (flag == 0)//flag==0,说明上面过程没有插入,所以这里直接将s放最后面
 89         {
 90             p_pio->next = s;//如果没有比s小的,即s应该排在最后
 91         }
 92     }
 93     ptr = s;//ptr需要指向新插入的结点
 94 }
 95 void ins_ctl(char name[])//插入一个目录结点
 96 {
 97     struct node* s = new struct node;
 98     s->ctl = s->file = s->next = NULL;
 99     strcpy(s->name, name);
100     if (!ptr->ctl)
101     {
102         ptr->ctl = s;
103     }
104     else
105     {
106         struct node* p = ptr->ctl;
107         struct node* p_pio = ptr;
108         int flag = 0;
109         while (p)
110         {
111             if (equal(s->name, p->name))
112             {//文件插入中这一步不需要,因为多同名的文件是要当成多个的,而同名目录可以共用
113                 ptr = p;//s与p同名,所以不用插入s了,直接令ptr指向p,直接return,然后处理下个结点时就会从p开始
114                 return;
115             }
116             else if (smaller(s->name, p->name))
117             {//以下方法与插入文件时相同
118                 flag = 1;
119                 s->next = p;
120                 if (p_pio->ctl == p)
121                     p_pio->ctl = s;
122                 else
123                     p_pio->next = s;
124                 break;
125             }
126             p_pio = p;
127             p = p->next;
128         }
129         if (flag == 0)
130         {
131             p_pio->next = s;
132         }
133     }
134     ptr = s;
135 }
136 void print_sp(int n)//输出空格的函数
137 {
138     for (int i = 0; i < n; i++)
139         cout << ‘ ‘;
140 }
141 int d = 0;
142 int cnt = -2;
143 struct node* p = &root;
144 void Print(int cnt, struct node* p)//输出最终结果的函数
145 {
146     struct node* s = p;
147     if (!p)return;
148     print_sp(cnt);
149     cnt += 2;//输出空格后,cnt增加2
150     cout << p->name << endl;//输出名字
151     //用递归输出,先输出完目录,再输出文件的思想
152     while (s->ctl)
153     {
154         Print(cnt, s->ctl);
155         s->ctl = s->ctl->next;
156     }
157     while (p->file)
158     {
159         Print(cnt, p->file);
160         p->file = p->file->next;
161     }
162 }
163 int main()
164 {
165     root.ctl = root.file = root.next = NULL;
166     strcpy(root.name, "root");
167     int n; cin >> n;
168     for (int i = 0; i < n; i++)
169     {
170         char s[300];
171         char s1[300];
172         cin >> s;
173         ptr = &root;//ptr初始化为root,因为每行输入都是从root开始处理的
174         //全局指针ptr永远代表某一结点插入时开始处理的位置
175         for (int j = 0, k = 0; j < 300; k++, j++)
176         {
177             if (s[j] == ‘\\‘)
178             {
179                 s1[j] = ‘\0‘;
180                 ins_ctl(s1);
181                 k = -1;
182                 memset(s1, 0, sizeof(char) * 300);
183                 continue;
184             }
185             else    if (s[j] == ‘\0‘)
186             {
187                 if (s[j - 1] == ‘\\‘)break;//这一句作用是处理如“a\b\”等最后的目录下没有文件的情况
188                 s1[j] = ‘\0‘;
189                 ins_file(s1);
190                 k = -1;//设为-1是因为本次循环结束进入下一次循环k+1==0,刚好从0开始
191                 memset(s1, 0, sizeof(char) * 300);
192                 break;
193             }
194             else
195             {
196                 s1[k] = s[j];//将输入一行中的某个结点的名字放到s1中
197             }
198         }
199     }
200     Print(0, &root);
201     return 0;
202 }

原文地址:https://www.cnblogs.com/2020R/p/12578616.html

时间: 2024-10-27 21:41:28

7-30 目录树 (30分)的相关文章

基础实验4-2.6 目录树 (30分)- 建树+先序遍历

解题思路:采用将多叉树转化为二叉树的方法(即利用孩子兄弟的结点结构)建立二叉树,最后再先序遍历输出即可 #include <stdio.h> #include <malloc.h> #include <string.h> struct TNode { int space;//记录打印空格数 int prior;//标记是文件还是目录,文件优先级0,目录优先级1(优先级大的优先) char name[261];//文件名 struct TNode *son,*sib;//

4.19免费公开课-软考·网络工程师考前30天冲刺提分策略解读

分享老师: [徐朋] 51CTO学院高级讲师,40万在线学员. 网络规划设计师高级工程师,高级项目经理,高级信息安全工程师. 分享大纲: 晚8:00-8:05 徐朋老师自我介绍(5分钟) 晚8:05-9:10 软考网络工程师考试全面解读(55分钟)<1>强化冲刺阶段学员待解决的问题分析(15分钟)<2>考前30天冲刺提分秘籍解读(50分钟)Ⅰ.上午考题冲刺提分秘籍及部分重要考点分类解析Ⅱ.下午考题冲刺提分秘籍及部分重要考点分类解析Ⅲ.考前30天学习计划与时间安排晚9:10-9:30

【Lua】Lua + LWT + ExtJS构建目录树

Lua处理后台逻辑,Lua lwt搭建后台程序,ExtJS根据后台传来的json数据构建目录树. 前台html和ExtJS代码不用多讲,直接上代码: treePanel.html 1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 5 <title>ExtJS TreePanel</

Vue组件之无限级目录树构建

渐渐,了解Vue也有一个月了,最近遇上个无限级目录树的小功能,为了能多学习避免自己操作dom或是网上下插件,下决心用Vue来解决当下问题,毕竟毛爷爷讲过,实践出真知,本次主要运用了组件之间的相互循环引用,然后就是循环组件与父组件之间的通信, 源数据格式采用了毗邻结构转为多维数组的形式,没办法,我也暂且只能想到这样去做,学习革命任重道远....... 1 Vue.component('item',{ 2 template:'<ul> 3 <li v-for="child in m

js实现目录树

第一步:HTML结构 1 <div class="folderDiv"> 2 <p>目录</p> 3 <ul class="folder"></ul> 4 </div> 第二步:CSS样式 1 /*目录树*/ 2 .folderDiv {width: 14%;float: left;height: auto;overflow: auto;border:1px solid #ccc;border-

jdk 1.7系列(三)处理目录和目录树

DirectoryStream<T> 接口 java.nio.file.DirectoryStream<T>接口和它的实现类提供的功能: 循环遍历目录中的子项,比如查找目录中的文件 用glob表达式(比如*Footbar*)进行目录子项匹配和基于MIME的内容检测(比如text/xml文件) 用walkFileTree方法实现递归移动.复制和删除操作 一.在目录中查找文件,列出目录下的xml文件 以此项目为示例: package com.gudongcheng.jdk7.nio;

表达式目录树Expression

表达式目录树是用于动态的linq语句的拼装在以前遇到数据筛选的情况下我们日常的操作是 1 Console.WriteLine("输入Name 不写为空"); 2 var name = Console.ReadLine(); 3 Console.WriteLine("输入PassWord 不写为空"); 4 var PassWord = Console.ReadLine(); 5 string sql = "select * from Student whe

Linux学习笔记之(2)~linux目录树概览和说明

献给知道mono,了解Jexus,对.net混搭技术感兴趣的朋友. linux目录树如下: 详解:/bin: 系统有很多放置执行档的目录,但/bin比较特殊.因为/bin放置的是在单人维护模式下还能够被操作的指令.在/bin底下的指令可以被root与一般帐号所使用,主要有:cat, chmod, chown, date, mv, mkdir, cp, bash等等常用的指令./boot: 这个目录主要在放置开机会使用到的档案,包括Linux核心档案以及开机选单与开机所需设定档等等. Linux

Linux目录树

Linux目录树(directory tree) 分层结构(不同于数据库文件系统),单个文件/目录的最大长度为255个字符,完整路径为4096个字符 特殊的文件系统 文件系统 挂载点 说明 Root / Linux系统运行的基点 Proc /proc 以文件系统的方式为访问系统内核数据的操作接口(2.4,2.6) Sysfs /sys 以文件系统的方式为访问系统内核数据的操作接口(2.6) Tmpfs /dev,/var/run,/var/lock 程序访问共享内存资源时使用的文件系统 Usbf