【问题标题】:Linked-lists in cc中的链表
【发布时间】:2021-06-26 20:16:52
【问题描述】:

我对 c 编码还很陌生,并且偶然发现了一个问题。下面的代码是我目前所拥有的。

我遇到的问题是语法,更具体地说是如何遍历列表。过去一周我一直在研究不同的资源,但没有人解释如何使用类似的 struct 数据类型。我尝试遍历列表的方式会导致错误,并且我无法在正确的位置添加作业,因为列表是按参考编号递增的。

我遇到的另一个问题是在函数 5 中。我不太确定如何通过 char 指针返回整数和字符值,除非你只返回整个 job_node。截至目前,我已将节点的值转换为字符。

由于我在 c 中编写的代码不多 - 关于如何在不更改函数值的情况下提高代码效率的任何其他建议都会非常有帮助。

【问题讨论】:

  • 你为什么不想返回一个指向(可选constjob_node的指针?对我来说,这看起来是正确的解决方案。您的调用者将需要两个成员、标识符和名称。它可以忽略链接指针。
  • create_job_node 不返回值。你肯定会收到一个编译器警告。
  • 您可以将 NULL 传递给 free,因此 if (lst != NULL){ free(lst); } 可以简单地重写为 free(lst)。无需进行冗余检查。
  • 旁注:不要在箭头运算符 (->) 周围放置空格。请将所有(例如)foo -> bar 更改为 foo->bar

标签: c linked-list nodes


【解决方案1】:

链表是节点的容器,每个节点都有一些数据负载。通常每个数据记录都有一个键,一个用于比较两条记录的值。在学生的作业中,数据通常是一个简单的字母或数字。在您的情况下是指向“职位”的指针。

下面我将向您展示另一种写他的方式。但首先...

请务必注意,该列表是节点容器,而不是职位列表。列表不是节点,节点不是列表,数据也不是节点。

像在程序中那样混合这些东西只会导致问题:例如,您将无法使用列表来包含其他数据。如果不更改数据,您将无法更改列表的实现。如果您更改职位发布中的字段,您将需要更改列表功能。只有问题。

示例

bool job_insert(int refNum, char job_name[], struct job_list * list);    

应该是这样的

    int     insert_l( Job* job_post ,List* the_list ,int(*compare_function)(void*,void*)); 

为什么?

  • 使用前一种方式,您可以只使用指向 Job 的指针 --- 通常,您应该使用 void*,这样您就可以使用数据记录中的任何内容,而无需更改参数列表。
  • 这样,如果您将字段添加到 Job 或将参考号更改为 char[] 以添加校验位,则无需在此处更改任何内容
  • compare_function()比较两个Job,如果第一个更大则返回-1,如果第二个更大则返回1,或者0。这样您可以随时更改排序标准,只需编写一个新的10行函数,然后已按新条件插入记录。 C qsort() 使用这个,C++ sort() 使用这个,Borland Turbo Pascal 在 80 年代使用这个。它简单灵活。
  • 函数可以这么简单
int compare_reference(void* a, void* b)
{
    int first =  ((Job*) a)->reference_number;
    int second = ((Job*) b)->reference_number;
    if (first < second ) return 1;
    if (first > second ) return -1;
    return 0;
}; 

并像这样使用

    int    res = insert_l( one_job, new_jobs, compare_reference );

如果res0 one_job 被插入new_jobs 列表中的正确位置。它也更容易阅读:根据条件将记录插入列表

如果在任何时候您需要使用降序或按其他标准排序,您只需要传递一个新函数。这意味着您可以使用相同的 List 相关函数来包含任何数据。这也是只使用指向数据元素的 void 指针的原因......

返回程序

这可能是一个测试文件来驱动你的测试:

    1    engineer
    2    magician
    3    astronaut
    4    actress
    5    truck driver
    6    writer

结构


typedef struct
{
  int       reference_number;
  char*     job_name;

}   Job;

typedef struct node_
{
    Job*            info; // pointer to data record
    struct node_    *next;
    struct node_    *prev;

}   Node;

typedef struct 
{
    unsigned  size; // actual size
    unsigned  capacity; // limit in # of nodes
    Node*     head;
    Node*     tail;

}   List;

您有一个List,它是Node 的集合。每个Node 都有一个指针info 指向一个Job,即数据记录。在Job 中,您有参考号和工作名称。 reference_number 之所以称为key,是因为它是用于比较Job 记录的字段。

List 没有引用 Job,只有 NodeNode 没有数据,只有一个指针。所以使用List 来包含歌曲、汽车或书籍,比如下一个作业很容易;)

功能

List*       create_l(unsigned); // return new List
List*       delete_l(List*); // erase one
int         insert_l( Job*,List*,int(*)(void*,void*)); // insert based on function
List*       merge_l(List*,List*,int(*)(void*,void*) ); // merge 2 lists into a 3rd
int         remove_by_ref_l(int,List*); // delete a record
char*       search_job_l(int,List*); // search for job description for a reference#

我相信现在您会看到一些额外的便利:

  • insert() 只接收一个指向 JobList 的指针,以及要比较的函数的名称 2。
  • create() 返回一个指向新 List 的指针,限制设置为最大节点数
  • remove() 获取参考号,如果在 List 中找到它,则删除记录并返回 0
  • search() 工作方式相同

我建议你这样写。如果您需要帮助,我可以提供更多代码。我今天没有时间写一个完整的例子。

【讨论】:

  • 这就是我们所说的答案...非常好...解释清楚...赞成
猜你喜欢
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
相关资源
最近更新 更多