文件目錄結構的樹形顯示(數據結構課程設計,樹、隊列,C語言描述)


一、要解決的問題

    給出某一個操作系統下目錄和文件信息,輸入的數據第一行為根目錄節點。若是目錄節點,那么它的孩子節點將在第二行中被列出,同時用一對圓括號“()”界定。同樣,如果這些孩子節點中某一個也是目錄的話,那么這個目錄所包含的內容將在隨后的一行中列出,由一對圓括號“()”界定。目錄的輸入輸入格式為:*name size,文件的輸入輸入格式為:name size。Name為一串不超過10個字符組成,並且字符串中不能有‘(’,‘)’,‘[‘,’]’和’*’。Size是該文件/目錄的大小,文件的size輸入值為該文件的大小,目錄的size輸入值都為1。樹結構最多10層,每一層最多2個文件/目錄。

要求編程實現將其排列成一棵有一定縮進的樹,輸出要求:第d層的文件/目錄名前面需要縮進8*d個空格,兄弟節點要在同一列上。並計算每一個目錄大小,目錄大小為所包含的所有子目錄和文件大小以及自身大小的總和。

例如輸入:

*/usr 1

(*mark 1 *alex 1)

(hw.c 3 *course 1) (hw.c 5)

(aa.txt 12)

輸出

|_*/usr[24]

     |_*mark[17]

     |      |_hw.c[3]

     |      |_*course[13]

     |            |_aa.txt[12]

     |_*alex[6]

           |_hw.c[3]

 

二、算法基本思想描述:

采用孩子兄弟雙親鏈表的數據存儲結構建立二叉樹,再先序遍歷該二叉樹輸出所有節點。輸出時,通過parent節點的第一個孩子是否有兄弟節點控制縮進輸出” |       ”或”         ”;目錄的大小為該目錄左子樹(以其第一個孩子為根的樹)所有節點的size和加上它本身大小。

 

三、設計

1. 數據結構的設計和說明

在一開始設計要采用的數據結構時,雖然課題只要求“樹結構最多10層(樹的深度),每一層最多2個文件/目錄”,考慮到問題的實際意義,我決定把它優化消除這一限制,於是采用孩子兄弟的數據結構,后來由於縮進輸出的需要又增加了parent域。

2. 關鍵算法的設計

1)輸入處理:從外部文件每讀入一行處理一行,數據結構的構造與讀入同時進行,提取節點的name[]域和size域建立該行所有節點。其間,利用隊列設立parentArray[]用來記錄所有的目錄節點地址,設置兩個虛擬指針rear和head,每增加一個目錄rear+1,head標記可作為當前節點parent域的目錄,每遇到一個‘)’ head+1處理下一個目錄包含的節點。當輸入文件結束時所采用的孩子兄弟雙親鏈表二叉樹也就建立完成。

(2)輸出處理:先序遍歷所建立的二叉樹,每個節點輸出一行,都是先通過其parent節點的第一個孩子是否有兄弟節點標記flag[0]~flag[i],然后從flag[i]~flag[0]控制輸出縮進符” |       ”或”         ”后再輸出該節點信息。

3. 數據結構圖:

 

四、源程序清單(Win7系統WinTC環境下編譯運行通過)

/*

     ========================================================

            課題:文件目錄結構的顯示

                       Author:Estrong. All Rights Reserved.

       指導老師:LinFang

                         2011年1月7日寫於福建工程學院.

     ========================================================

*/

#include "stdio.h"

#include "string.h"

#define Null 0

#define MAX 200

                /*輸入文件每行應不超過MAX個字符*/

 

typedef struct node /*采用孩子兄弟雙親鏈表的存儲結構*/

{

 char name[12];

 unsigned int size;

 struct node *parent,*first_child,*next_sibling;

}BinTNode,*BinTree;

 

 

 /* 添加新節點 */

BinTree New_BinTNode(char str[],int *I,BinTree parentArray[],int *head,int *rear)

{ int i=0;

  BinTree bt;

  bt=(BinTNode *)malloc(sizeof(BinTNode));

  bt->parent=parentArray[*head];  /*鏈接雙親結點確定歸屬目錄*/

  bt->first_child=Null;

  bt->next_sibling=Null;

  if(str[*I]=='*')

   {(*rear)++; parentArray[*rear]=bt;}

  while(str[*I]!=' ')

    {

       bt->name[i]=str[*I];

       (*I)++;i++;

     }

  bt->name[i]='\0';(*I)++;

  bt->size=str[*I]-'0';(*I)++;

  while ((str[*I]!=' ')&&(str[*I]!=')')&&((*I)<strlen(str)-1))      /*條件(*I)<strlen(str)-1)是考慮到根節點沒有‘ ’和')'*/

    {

     bt->size=bt->size*10+(str[*I]-'0');

     (*I)++;

    }

  return bt;

}

 

 

/* 創建數據(將輸入數據轉化為所采用的樹結構) */

BinTree Create_BinTree(FILE *input)

{  int I=0,rear=0,head=1;   /*parentArray[head]用來記錄當前節點應指向的parent目錄節點*/

                            /*parentArray[rear]用來記錄最后一個目錄節點*/

   BinTree parentArray[MAX];/*parentArray[]用來記錄所有的目錄節點地址*/

   BinTree root,bt,pbt;

   char str[MAX];

   fgets(str,MAX,input);

   root=New_BinTNode(str,&I,parentArray,&head,&rear);

   root->parent=Null;   /* 在創建根節點時其parent的賦值是隨機的,這里給它賦回空 */

   while(!feof(input))

     {I=1;                           /*I是輸入文件每行字符串中的下標,貫穿該行字符處理始末*/

      fgets(str,MAX,input);

      while(I<=(strlen(str)-1))

        {

          if(str[I]!=')')

           {

              bt=New_BinTNode(str,&I,parentArray,&head,&rear);

              parentArray[head]->first_child=bt;

              pbt=bt;

              do       /*創建並鏈接一對括號里的所有兄弟節點*/

               {

                 if(str[I]==' ')

                   {

                     I++;

                     pbt->next_sibling=New_BinTNode(str,&I,parentArray,&head,&rear);    /*創建兄弟節點*/

                     pbt=pbt->next_sibling;

                    }

                }while(str[I]!=')') ;

              head++; I=I+3;   /*  此時遇到右括號head+1處理下一個目錄;I+3跳過") ("  */

           }

          else

            {head++ ; I=I+3;}  /*  此時也遇到右括號  */

        }

     }

  return root;

}

 

 

/* 求目錄大小 */

int SIZE(BinTree bt)      /*返回當前目錄左子樹的大小(未加上原目錄大小)*/

{ int size;

  if(bt)

     size=bt->size+SIZE(bt->first_child)+SIZE(bt->next_sibling);

  else size=0;

  return size;

}

 

 

/* 輸出單個節點 */

void out(BinTree bt,FILE *output)

{ char size_str[10];

  BinTree pbt=bt->parent;

  int i=-1,j=0,k;

  int flag[11];       /*flag[i]用來控制縮進,子目錄深度可以設置,目前設為11*/

  for(k=0;k<11;k++) flag[k]=0;

  if(bt->name[0]=='*') bt->size=bt->size+SIZE(bt->first_child);

                       /*目錄的大小為該目錄本身大小及其左子樹(以其第一個孩子為根的樹)所有節點的size和*/

  while(pbt!=Null)

    {

     i++;

     if(pbt->next_sibling) flag[j]=1;       /*輸出時flag[i]=1縮進"|       "   */

     else flag[j]=0;                        /*輸出時flag[i]=0縮進"        "    */

     pbt=pbt->parent;

     j++;

    }

  while(i>=0)

    {

      if(flag[i]) {printf("|       ");fprintf(output,"|       ");}

      else {printf("        ");fprintf(output,"        ");}

      i--;

    }

  printf("|_%s[%d]\n",bt->name,bt->size);

  fprintf(output,"|_%s[%d]\n",bt->name,bt->size);

}

 

 

/* 先序遍歷輸出整棵樹 */

void OUTPUT(BinTree bt,FILE *output)

{

  if(bt)

    {

      out(bt,output);

      OUTPUT(bt->first_child,output);

      OUTPUT(bt->next_sibling,output);

    }

}

 

 

/* 主函數 */

main()

{ FILE *input,*output;

  BinTree root;

  if((input=fopen("input.txt","r"))==NULL)

    {

     printf("Cannot find the file!   Strike any key to exit!");

     getch();

     exit(1);

    }

  output=fopen("output.txt","w");

  root=Create_BinTree(input);

  OUTPUT(root,output);

  getch();

  fclose(input);fclose(output);

}

 

 

五、測試數據及測試結果:

(注:以下測試數據置於外部文件input.txt里)

*/kqss 1

(*mark 1 *alex 1 *course 1 aa.txt 12 hw.c 5 hjh.c 4 gffg.c 5)

() (kkhw.c 3 *course 1) (ghw.c 5 *test 1 abcd.exe 13 *fdg 1 hw.c 5 hjh.c 4)

(aa.txt 2 kqss.c 100 hgfgsdf.h 35 ghgjh.mp3 7) () (arfe.txt 12 kqss.c 100 fdfs.h 35)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM