数据结构与算法分析——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);
}