我对c语言的编码还很陌生,偶然发现了一个问题。到目前为止,下面的代码就是我所拥有的,手头的问题是如何循环通过节点job_list。
我们有两个节点,第一个节点创建一个以参考号(整数(和作业名称(字符串-字符数组(为参数的基本作业帖子,第二个节点是一个包含作业帖子的列表,其中job_node是一个参数,第二个子节点是标准structjob_list*next参数。
我想你把一些事情搞混了。。
单链接列表(据我所知,您正在使用(不是一个固定大小的数据结构。它甚至不是一个不断增加的空间数据结构。链接列表使用的内存量恰好您希望在其中保持的内存量。
链表是一个节点列表。您可以创建列表,它将是一个空列表。
然后,您可以添加具有所需数据的节点和插入的每个节点-创建一个新节点(在堆上=动态分配(,该节点将包含您的数据并链接到列表。
列表中的每个数据节点都将有一个指向它的node_next和指向该特定节点的node_prev(head和tail将没有这两个节点。head将指向node_next,但没有指向它的node_prev,tail只有指向它的节点_prev(。
因此,如果要创建列表,则必须动态分配列表的空间,其中包含2个节点:head和tail(或end(。
这是创建函数的一个例子:
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);
}
然后,您将能够在特定节点之前或之后插入节点——这取决于您将如何实现:
如果要在:
之前实现insert,则必须封装列表结构,并防止用户将头发送到insert之前
或者您可以每次检查您的插入功能是否获得列表的标题并更新列表的标题(您可以在标题之后插入并将标题数据复制到标题->下一个节点,然后将标题用于用户希望位于列表标题的数据。
如果你想在:
之后实现插入,你必须检查用户是否向你发送了尾部(也称为dummy_node,因为它指向dummy_node->next=NULL(,并使用我之前提到的相同方法,只是相反。。
这是在之前插入的一个例子-在这个例子中,我使用了指向node_t的slist_iter_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,您必须编写create函数、insert函数和destroy函数(您必须释放所有动态分配的内存(。
您可以添加更多的函数,如remove、search data、clear list、is empty等。如果您选择封装此实现,并向用户隐藏列表的结构和节点的结构,则必须添加更多的函数,如get data函数、get next node等。。
您提到,如果列表中不存在此数据,则需要插入,这样您就可以从insert函数发送到find函数。
你的函数需要看起来像这样:
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 failedn");
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 failedn");
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;
}
正如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,所以你可以看到这些函数的作用。