我对用 c 编写代码还很陌生,并且偶然发现了一个问题。下面的代码是我到目前为止所拥有的,手头的问题是如何遍历节点 job_list。
我们有两个节点,第一个节点创建了一个基本的招聘信息,以参考号(一个整数)和职位名称(一个字符串 - 一个字符数组)作为参数,第二个是一个包含招聘信息的列表job_node 是一个参数,第二个是标准的 struct job_list * next 参数。
答案 0 :(得分:0)
我认为你混淆了一些东西..
单独链接列表(这就是我所理解的)不是固定大小的数据结构。它甚至不是一个增加空间的数据结构。链接列表完全使用您想要在其中保存的内存量。
链接列表是节点列表。您可以创建列表 - 它将是一个空列表。
然后,您可以添加具有所需数据的节点以及您插入的每个节点 - 创建一个新节点(在堆上=动态分配),它将包含您的数据并将链接到列表.
列表中的每个数据节点都有一个指向的node_next,以及指向这个特定节点的node_prev(头和尾不会有这2个节点。头将指向node_next但不会有node_prev指向哪个节点到它,尾部只有 node_prev 将指向它)。
因此,如果要创建列表,则必须动态分配包含2 个节点:头和尾(或尾)的列表空间。
这是一个创建函数的例子:
slist_t *SlistCreate(void)
{
slist_t *list = malloc(sizeof(slist_t));
slist_iter_t dummy = NULL;
if(NULL == list)
{
return (NULL);
}
dummy = malloc(sizeof(node_t));
if(NULL == dummy)
{
free(list);
return (NULL);
}
dummy->next = NULL;
dummy->data = (void *)list;
list->head = dummy;
list->tail = dummy;
return (list);
}
然后您将能够在特定节点之前或之后插入节点 - 这取决于您将如何实现:
如果你想实现插入之前:
您将不得不封装列表结构并防止用户发送您的头部之前插入。
或者您可以每次检查您的插入函数是否获取列表的头部并更新列表的头部(您可以在之后插入并将头部数据复制到头部->下一个节点,然后将头部用于用户的数据想排在列表的首位。
如果你想实现插入:
您必须检查用户是否向您发送了尾部(也称为 dummy_node,因为它指向 dummy_node->next = NULL),并使用我之前提到的相同方法,只是以相反的方式..
这是一个 insert before 的例子 - 在这个例子中我使用了 slist_iter_t ,它是指向 node_t 的指针 - 用户没有暴露于任何这个结构(不是列表结构或节点结构):
slist_iter_t SlistInsert(slist_iter_t iterator, const void *data)
{
slist_t *ptr = NULL;
slist_iter_t dup = (slist_iter_t)malloc(sizeof(node_t));
if(NULL == dup)
{
return(NULL);
}
assert(NULL != iterator);
dup->data = iterator->data;
dup->next = iterator->next;
iterator->data = (void *)data;
iterator->next = dup;
if(NULL == dup->next)
{
ptr = (slist_t *)dup->data;
ptr->tail = dup;
}
return (iterator);
}
因此,要使用此 DS,您必须编写创建函数、插入函数和销毁函数(您必须释放所有动态分配的内存)。
您可以添加更多功能,例如删除、搜索数据、清除列表、为空等。如果您选择封装此实现并向用户隐藏列表结构和节点结构,则必须添加更多功能,例如获取数据功能、获取下一个节点等..
您提到如果列表中不存在此数据,则需要插入,以便您可以从插入函数发送到查找函数。
你的函数需要看起来像这样:
struct job_list {
struct job_node * front;
struct job_list * next;
};
struct job_node {
int reference_number;
char * job_name;
struct job_node *next;
};
对于您的第一个功能:
struct job_node *JobListCreate(void)
{
struct job_node *list = malloc(sizeof(struct job_node));
struct node_job dummy = NULL;
if(NULL == list)
{
return (NULL);
}
dummy = malloc(sizeof(node_t));
if(NULL == dummy)
{
free(list);
return (NULL);
}
dummy->next = NULL;
dummy->data = (void *)list;
list->head = dummy;
list->tail = dummy;
return (list);
}
对于您的第二个功能:
void JobListInsertInFront(struct job_node *list, int reference_number, char * job_name)
{
slist_t *ptr = NULL;
struct node_job dup = NULL;
assert(NULL != list);
dup = (struct node_job)malloc(sizeof(node_t));
if(NULL == dup)
{
printf("Allocation failed\n");
return;
}
dup->reference_number = list->head->reference_number;
dup->job_name = list->head->job_name;
dup->next = list->head->next;
list->head->reference_number = reference_number;
list->head->job_name = job_name;
list->head->next = dup;
return;
}
对于最后一个函数:
bool JobListInsertIfNotExist(struct job_node *list, int reference_number, char * job_name)
{
slist_t *ptr = NULL;
struct node_job dup = NULL;
assert(NULL != list);
while (NULL != dup)
{
if (dup->reference_number == reference_number && dup->job_name == job_name)
{
return false;
}
dup = dup->next;
}
dup = (struct node_job)malloc(sizeof(node_t));
if(NULL == dup)
{
printf("Allocation failed\n");
return;
}
dup->reference_number = list->head->reference_number;
dup->job_name = list->head->job_name;
dup->next = list->head->next;
list->head->reference_number = reference_number;
list->head->job_name = job_name;
list->head->next = dup;
return true;
}
答案 1 :(得分:0)
正如Jack Lilhammers在评论中指出的那样,您的代码非常复杂,而且错误很多,所以我写了一些通用函数,您可以进行相应的修改。
这是我们将要使用的基本结构:
struct node {
int data;
struct node *next;
};
那么这就是您创建新节点的方式:
#include <stdio.h>
#include <stdlib.h>
struct node *new_node(int data, struct node *next)
{
struct node *new = malloc(sizeof *new);
if (!new) {
printf("Error: memory allocation failed");
exit(EXIT_FAILURE);
}
new->data = data;
new->next = next;
return new;
}
您最初会像这样调用函数:
struct node *head = new_node(5, NULL);
通常你会做这样的事情来检查链表中是否存在具有特定数据的节点:
#include <stdbool.h>
/* Return whether or not the node exists */
bool node_exists(struct node *head, int data)
{
struct node *cursor = head;
while (cursor != NULL) {
if (cursor->data == data)
return true;
cursor = cursor->next;
}
return false;
}
如果你想在链表的末尾插入一个新节点,它是这样工作的:
void insert_last(struct node *head, struct node *new)
{
struct node **cursor = &head;
while ((*cursor) != NULL)
cursor = &(*cursor)->next;
*cursor = new;
}
如果数据不存在,你可以结合最后两个函数,只在链表的末尾插入一个新节点:
#include <stdbool.h>
/*
* Return whether or not the node exists. If it exists,
* insert the new node at the end of the linked list.
*/
bool new_insert_last(struct node *head, struct node *new)
{
struct node **cursor = &head;
while ((*cursor) != NULL) {
if ((*cursor)->data == new->data)
return true;
cursor = &(*cursor)->next;
}
*cursor = new;
return false;
}
这个函数可以这样调用:
new_insert_last(head, new_node(3, NULL));
我已经创建了一个 GitLab Snippet,因此您可以看到运行中的函数。