//用孩子兄弟表示法的结构来存储文件目录 //用先序查找 typedef struct CSNode { char data[2048]; struct CSNode *firstchild, *nextsibling , *parent; }CSNode;
// 版权所有 (C)2007, ***(成都)有限公司。 // // 描述: // 解析文件目录树 //树是一种常用的数据结构,如文件目录结构就是一种树形结构。现给定一个目录路径(如:C:/Data/), //请实现一个目录结构树,并将其子目录和子文件打印出来,具体效果如windows命令tree。 //要求: //1、先遍历目录,将目录树保存到内存 //2、实现一个打印输出函数,将保存的目录树打印输出 // 作者:陈进宇 [email protected] #include <iostream> #include <string.h> #include <afx.h> #include <cwchar> #include "TreeNode.h" #define MAX_LEN 1024 using namespace std; struct CSNode *GetFiles(char *strPath,struct CSNode *treeN);//递归查找文件和文档 struct CSNode *InsertSibling(struct CSNode *pRoot,struct CSNode *pParent,char *filename);//是兄弟 struct CSNode *InsertChild(struct CSNode *pRoot,char *filename);//是孩子 struct CSNode *CreateTree(struct CSNode *node);//创建树节点 void PrintTree(struct CSNode *node,int nLevel); void DeleteTree(struct CSNode *node); void main() { struct CSNode *root; root = CreateTree(root); root = GetFiles("E://",root); PrintTree(root,0); DeleteTree(root); } /// <summary> /// 创建第一个节点 /// </summary> /// <param name="node">[out] struct CSNode *node:树的根。</param> /// <returns>返回的是树的根</returns> struct CSNode *CreateTree(struct CSNode *node) { node = (struct CSNode *)malloc(sizeof(struct CSNode)); if(node == NULL) { printf("Insufficient memory available/n"); } else { strcpy(node->data,"E://project//C++_project//"); } return node; } /// <summary> /// 递归查找节点 /// </summary> /// <param name="treeN">[out] struct CSNode *treeN:当前节点。</param> /// <param name="strPath">[in] char *strPath:查找的路径。</param> /// <returns>返回的是树的根节点</returns> struct CSNode *GetFiles(char *strPath,struct CSNode *treeN) { WIN32_FIND_DATA FindFileData; HANDLE hFile; bool isSibling = false; struct CSNode *node = treeN; char szPath[MAX_LEN]; char szFind[MAX_LEN]; strcpy(szPath,strPath); strcpy(szFind,szPath); strcat_s(szFind,"*.*"); hFile = FindFirstFile(szFind,&FindFileData); while(INVALID_HANDLE_VALUE != hFile) {//创建node孩子 struct CSNode *p; struct CSNode *pCur = p;//辅助节点 p = node;//创建节点 char cfilename[256]; strcpy(cfilename,FindFileData.cFileName); if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if((strcmp(cfilename,".") != 0) &&(strcmp(cfilename,"..") != 0))//"."是当前路径,".." 是上一级的路径 { if(isSibling == false)//是孩子 { p = InsertChild(p,cfilename); } else//是兄弟 true { p = InsertSibling(pCur,node,cfilename); } // cout <<"Dir:" << FindFileData.cFileName << endl; for(int i = 0; i < strlen(szFind);i++) { szFind[i] = NULL; } strcpy(szFind,szPath); strcat_s(szFind,cfilename); strcat_s(szFind,"//"); GetFiles(szFind,p); } } else//是文档 { if(isSibling == false)//孩子 { p = InsertChild(p,cfilename); } else//兄弟 { p = InsertSibling(pCur,node,cfilename); } //cout << FindFileData.cFileName << endl; } if(!FindNextFile(hFile,&FindFileData))//没有兄弟 { hFile = INVALID_HANDLE_VALUE; } else//有兄弟 { if((strcmp(cfilename,".") == 0) || (strcmp(cfilename,"..") == 0)) { isSibling = false; } else { isSibling = true;//是兄弟 } } } FindClose(hFile); return node; } /// <summary> ///如果是该节点的孩子,就插入节点 /// </summary> /// <param name="pRoot">[in] struct CSNode *pRoot:当前节点。</param> /// <param name="filename">[in] char *filename:文件名称。</param> /// <returns>返回的是插入孩子后的节点</returns> struct CSNode *InsertChild(struct CSNode *pRoot,char *filename)//是孩子 { struct CSNode *pNode, *node; pNode = (struct CSNode *) malloc (sizeof(struct CSNode)); pRoot ->firstchild = pNode; pNode ->parent = pRoot; pNode ->nextsibling = NULL; pNode ->firstchild = NULL; node = pNode->nextsibling; strcpy(pNode->data,filename); return pNode; } /// <summary> /// 如果是该节点的兄弟,就插入节点 /// </summary> /// <param name="pRoot">[in] struct CSNode *pRoot:当前节点。</param> /// <param name="pParent">[in] struct CSNode *pParent:当前节点的父节点。</param> /// <param name="filename">[in] char *filename:文件名称。</param> /// <returns>返回的是插入兄弟后的节点</returns> struct CSNode *InsertSibling(struct CSNode *pRoot,struct CSNode *pParent,char *filename)//是兄弟 { struct CSNode *pNode; pNode = (struct CSNode *) malloc (sizeof(struct CSNode)); pRoot ->nextsibling = pNode; pNode ->parent = pParent; pNode ->firstchild = NULL; pNode ->nextsibling = NULL; strcpy(pNode->data,filename); return pNode; } /// <summary> /// 把创建的树打印出来 /// </summary> /// <param name="node">[in] struct CSNode *node:树的根节点。</param> /// <param name="nLevel">[in] int nLevel = 0:寻找节点的深度。</param> void PrintTree(struct CSNode *node , int nLevel = 0) { if(!node) return; static char buffer[100]; while(node != NULL) { const int t1 = max(0,nLevel - 1); for(int i = t1 << 2;i > 0 ;buffer[--i] = ' ');//每一级缩进4个字符的位置,这里先把buffer的0到(t1 - 1) * 4 个字符全部设置为空格 for(int i = (t1 << 2)-4; i >= 0 ;buffer[i] = '|',i-=4);//把buffer中0,4,8,12..... 位置上的字符都设置为|; if(nLevel) strcpy_s(&buffer[t1 << 2],5,"|___");//把最后连接文件之前的设置为"|___" strcat_s(buffer,node ->data);//最后连接文件名 printf("%s/n",buffer); PrintTree(node ->firstchild,nLevel + 1);//打印子节点 CSNode *tmpNode = node ->nextsibling;//循环下一个节点 node = tmpNode; } } /// <summary> /// 释放树空间 /// </summary> /// <param name="node">[in] struct CSNode *node:树的根节点。</param> void DeleteTree(struct CSNode *node) { if(!node) return; static CSNode *ptemp;//删除节点,临时保存地址,定义为静态变量,递归的时候不保存此变量的现场,节约堆栈 while(node) { DeleteTree(node ->firstchild);//每次递归时保存现场,出来时恢复现场 ptemp = node; node = node ->nextsibling; free(ptemp); } }