数据结构与算法分析——c语言描述 第四章 树 分级文件系统
编程书有一个特点,就是看的时候觉得很简单,但是写代码就蒙了,各种出错,不停debug,想办法,重新写,再debug……是一个不停思考迭代的过程。因为原理大体简单,但是细节就麻烦得不得了。
模块化,分功能。就这样
几个有意思的地方,递归解析地址,递归遍历。
tree.h
typedef char* ElementType; #ifndef _Tree_H #define _Tree_H struct TreeNode; typedef struct TreeNode *PtrToNode; typedef struct TreeNode *Tree; Tree createTree(); void makeEmpty(Tree t); void insert(char * address, char *filename, Tree t); Tree del(ElementType x, Tree t); void listDirectory(Tree t); #endif
tree.c
#include"tree.h" #include"fatal.h" #include<string.h> #define NAME_LENGTH 30 struct TreeNode { ElementType element; PtrToNode firstChild;//儿子 PtrToNode nestSibling;//兄弟姐妹 }; static void delTreeNode(PtrToNode p) {//深度优先删除 if (p != NULL) { PtrToNode child = p->firstChild; PtrToNode sibling = p->nestSibling; free(p->element); free(p); if (child) delTreeNode(child); if (sibling) delTreeNode(sibling); } } static PtrToNode addressToPtr(char * address, Tree t) {//广度优先搜索文件 char *end = strchr(address, '/'); int isLastName = 0; if (end == NULL)//当前调用的地址是最后一个 { isLastName = 1; end = address; while (*end) end++; } char tempName[NAME_LENGTH];//为了用strcmp,所以复制了,其实自己写更好 int cursor_tempname = 0; for (char *p = address; p != end; p++) { tempName[cursor_tempname++] = *p; } tempName[cursor_tempname] = '\0'; PtrToNode Ptr_sameLevel = t;//搜索这一层的目录名字是否相同 do { if (strcmp(Ptr_sameLevel->element, tempName) == 0)//相同 break; Ptr_sameLevel = Ptr_sameLevel->nestSibling;//不相同,查下一个目录 } while (Ptr_sameLevel); if (Ptr_sameLevel && isLastName)//找到了 return Ptr_sameLevel; else if (Ptr_sameLevel && Ptr_sameLevel->firstChild && isLastName == 0)//islastname避免end+1溢出,否则如果是最后一个地址那么比出错 return addressToPtr(end + 1, Ptr_sameLevel->firstChild); else Error("wrong address"); } Tree createTree() { Tree t = malloc(sizeof(struct TreeNode)); t->firstChild = NULL; t->nestSibling = NULL; t->element = malloc(sizeof(char)*NAME_LENGTH); strcpy(t->element, "usr"); return t; } void makeEmpty(Tree t) { if (t != NULL) { delTreeNode(t->firstChild); t->firstChild = NULL; t->nestSibling = NULL; strcpy(t->element, "usr"); } } void insert(char * address, char *filename, Tree t) { PtrToNode p = addressToPtr(address + 1, t); PtrToNode child = p->firstChild; PtrToNode newNode = malloc(sizeof(struct TreeNode)); newNode->firstChild = NULL; newNode->nestSibling = NULL; newNode->element = malloc(sizeof(char)*NAME_LENGTH); strcpy(newNode->element, filename); if (child == NULL) { p->firstChild = newNode; } else { while (child->nestSibling)//其实也可以在第一个插入 child = child->nestSibling; child->nestSibling = newNode; } } static printName(PtrToNode p, int depth) { while (depth--) printf(" "); printf("%s\n", p->element); } static void listDir(Tree t, int depth) { if (t) { printName(t, depth); PtrToNode child = t->firstChild; while (child) { listDir(child, depth + 1); child = child->nestSibling; } } } void listDirectory(Tree t) { listDir(t, 0); }
main.c
#include"tree.h" #include<stdio.h> struct TreeNode { ElementType element; PtrToNode firstChild;//儿子 PtrToNode nestSibling;//兄弟姐妹 }; int main() { Tree t = createTree(); insert("/usr", "aaa", t); insert("/usr", "bbb", t); insert("/usr", "ccc", t); insert("/usr/bbb", "ddd", t); listDirectory(t); }