Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用C语言设计单链表API的函数原型_C_Api_Linked List_Function Prototypes - Fatal编程技术网

用C语言设计单链表API的函数原型

用C语言设计单链表API的函数原型,c,api,linked-list,function-prototypes,C,Api,Linked List,Function Prototypes,我正在用C重写我几年前学习的所有数据结构,以增加我对数据结构和C语言的理解。我正在做的第一个是单链表,所以我正在为它们设计一个API。我还没有写任何实现,但我想得到一些关于我的函数原型的反馈,以确保我所做的是合理的和合乎逻辑的 首先,我要说几句话: 我希望很多人会建议为节点结构使用typedef,但这是个人的决定,我不喜欢使用typedef结构 我对返回类型和值的选择最不确定。我有两个函数,它们返回指向已删除节点的数据变量的指针。这些函数从列表中删除节点,保存指向数据的指针,并释放节点。这意味着

我正在用C重写我几年前学习的所有数据结构,以增加我对数据结构和C语言的理解。我正在做的第一个是单链表,所以我正在为它们设计一个API。我还没有写任何实现,但我想得到一些关于我的函数原型的反馈,以确保我所做的是合理的和合乎逻辑的

首先,我要说几句话:

  • 我希望很多人会建议为节点结构使用typedef,但这是个人的决定,我不喜欢使用typedef结构

  • 我对返回类型和值的选择最不确定。我有两个函数,它们返回指向已删除节点的数据变量的指针。这些函数从列表中删除节点,保存指向数据的指针,并释放节点。这意味着需要用户释放返回的数据。这是坏形式吗?我不确定如何以允许静态返回数据的方式执行此操作,因为这需要事先知道数据的大小,这会削弱库的实用性

  • 我想让API支持所有可以用单链表完成的有用的事情,其中之一就是实现堆栈。单链表上的push/pop操作让我感到困扰的一点是,似乎有些人脑子里有这样的想法:push/pop操作只应该发生在列表的末尾。堆栈是后进先出机制(LIFO),如果需要在尾部(末端)执行推/弹出操作,则不适合于单链表。这显然是因为使用列表的尾部而不是头部效率很低,因为只有遍历列表才能到达最后一个元素。下面的push/pop函数模拟堆栈的行为,但操作发生在列表的前面。这是一个糟糕的设计吗

  • 以下是包含元素的列表示例:

    [SENTINEL]->[0]->[1]->[2]->[3]->NULL

    每个节点都属于struct node类型。结构节点是具有数据和下一个字段的结构:

    struct node {
        void *data;
        struct node *next;
    }
    
    此实现将使用sentinel节点简化边界条件。每个列表都有一个哨兵节点,位于列表的前面

    空列表包含一个指向null的sentinel节点,如下所示: [哨兵]->NULL

    列表的类型为struct sllist。struct sllist有一个sentinel字段,其中包含指向sentinel节点的指针:

    struct sllist {
        struct node *sentinel;
    }
    
    最后,这里是操作及其相关功能原型的列表(带说明):


    如果有任何明显不合适、奇怪或设计不当的地方,请告诉我。

    链表通常是更高级别数据结构的实现细节,即队列、列表、堆栈等。。。因此,我将确保实施每个项目所需的所有操作<代码>后推,
    前推
    前推
    后推
    前推
    后推
    ,当然还有随机访问

    至于有效负载,用户应该负责分配和解除分配。毕竟,它们可能在堆栈上传递一个指向内存的指针,而您肯定不希望释放该内存。另一种方法是在插入时复制有效负载(即memcpy),然后可以确保在pop时释放内存,并且不会对用户造成任何意外行为:这是以数据的线性副本为代价的

    此外,将链接列表修改为以下内容可能会有所帮助:

    struct sllist {
    struct node *head;
    struct node *tail;
    struct node *current;
    unsigned size;
    }
    

    再加上一点代码,这可能对感谢更有意义,这一切都非常有用。你能指定前面和后面的功能是什么吗?此外,当前的目标是什么?当然,我可以看到拥有这个尺寸的好处。另外,随机访问是指索引访问,对吗?@oddlogic front和back分别提供对前端和后端有效负载的访问,而不从列表中删除元素,而pop_front或pop_back则返回有效负载并从列表中删除元素。Current提供列表中的当前位置,并将提供更快的随机访问。例如,您可以有一个insert函数,它不需要在之后插入节点,而是在当前位置插入。它还将使线性迭代更容易。随机访问确实意味着通过索引进行访问。@oddlogic head和tail为您提供固定的时间弹出并推送到列表的前面和后面,这实际上使链表变得有用。@oddlogic还注意到,在单个链表中,在固定的时间内弹出并推送到后面是不可能的。谢谢你的澄清。因此,如果我有一个函数,它只接受一个有效载荷参数,用于相对于存储在current中的节点进行插入,那么它实际上必须在包含在current中的节点之后进行插入,对吗?当前节点之前没有指向该节点的指针,因此无法链接该节点。我可能遗漏了什么。你的意见很有价值。
    struct sllist {
    struct node *head;
    struct node *tail;
    struct node *current;
    unsigned size;
    }