• 7-30 目录树 (30分)


    主要思路:

    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] == '' && s2[j] != '')
     27                 {
     28                     return true;
     29                 }
     30                 if (s1[j] != '' && s2[j] == '')
     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] = '';
    180                 ins_ctl(s1);
    181                 k = -1;
    182                 memset(s1, 0, sizeof(char) * 300);
    183                 continue;
    184             }
    185             else    if (s[j] == '')
    186             {
    187                 if (s[j - 1] == '\')break;//这一句作用是处理如“a”等最后的目录下没有文件的情况
    188                 s1[j] = '';
    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 }
  • 相关阅读:
    CORS跨域解决方案
    修改数据库排序规则实践总结
    【转】通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?
    调用远程数据库的T-SQL和SP(SQLSERVER)
    解决在微信网页中百度地图定位不准确的问题
    VUE小知识点
    实现鼠标移过时,显示图片的功能
    实现导出功能
    两数据库表之间迁移插入数据
    IIS配置FTP
  • 原文地址:https://www.cnblogs.com/2020R/p/12578616.html
Copyright © 2020-2023  润新知