代码之家  ›  专栏  ›  技术社区  ›  GPWR

C文件管理器的高效链表设计

  •  1
  • GPWR  · 技术社区  · 1 年前

    背景。

    我正在用C制作一个文件管理器。为了在ncurses的CWD中显示文件列表,我选择将文件列表实现为以下结构的单链表:

    typedef struct FileNode {
        char name[256]
        struct FileNode* next;
    } FileNode;
    

    我确信文件名永远不会超过255个字符加上空终止符。这是ext2、ext3、ext4、BTRFS、XFS、ZFS和exFAT的标准配置。(我不熟悉DOS文件系统,但我只是针对UNIX。)

    我必须考虑将给定文件重命名为更长名称的情况,在这种情况下,我只会更改该文件节点的名称 不 重建整个链表。然而,如果名称发生了变化,那么该结构体在列表中的位置也可能发生变化,因为 列表是按字母顺序排列的 属于 FileNode 名字。

    注意。 我可能会增加成员 文件节点 例如,稍后使用struct来确定用户在ncurses接口中选择了列表中的哪些文件。

    问题。

    因为 文件节点 struct为文件名保留了256个字节,对于具有大量文件且名称相对较短的目录,将浪费大量内存。我的文件管理器是通用的,所以我可以很好地想象发生这种情况的场景。

    在这种情况下,高级程序员会怎么做? 在创建大型文件列表或同时重命名多个文件时,文件名的动态分配会导致更大的开销。(这将是我的文件管理器的一个功能。)

    我调查过的事情。

    在考虑了FAM一段时间后(见下面的代码片段),我注意到除非我选择这样做,否则文件重命名会变得复杂 释放节点并创建一个新节点 重命名文件时。这是一个好的选择吗?代价高昂的部分是首先检查所有文件名的长度,以便生成一个单独适合这些长度的结构列表。重复我之前的问题, 一个高级程序员会做什么 ?

    typedef FileNode {
        struct FileNode* next;
        char name[]; // this member should be the last
    } FileNode;
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   Kenzo    1 年前

    从算法的角度来看:

    对于始终排序的列表,您可以使用以下数据结构 AVL or Red-Black Trees 在根据您的选择创建、删除或重命名文件时,保持FileList的排序顺序。

    要提高大型目录的性能,请执行以下操作:

    受linux内核的启发,使用哈希表进行文件名查找 dcache

    将文件名(或文件ID)映射到 FileNode 红黑树中用于O(1)查找的指针。

    要处理重命名情况,我会:

    1. 使用哈希表检索FileNode指针。
    2. 通过FileNode释放占用的内存->名字。从红黑树中删除节点并重新平衡。
    3. 重新分配所需的内存。
    4. 将新名称复制到FileNode->名字。将节点插入红黑树中,然后再次重新平衡。

    进一步的改进范围: