首页 > 解决方案 > 如何使用包含 void 指针和指向该结构的递归指针的单链表结构格式在 C 中创建嵌套列表?

问题描述

任务是将现有列表按长度排序到另一个嵌套列表中。

["x", "yy", "zzz", "f", "gg"] ergeben 
 [["x", "f"], ["yy",
"gg"], ["zzz"]] 

我正在考虑使用 Struct Node 中的 void 指针来存储另一个列表,即主列表的每个节点内的列表。但我不断收到以下错误

dereferencing 'void *' pointer

我也尝试过类型转换。可能还有其他问题,但由于上述问题,我还没有到达那里。

typedef struct Node {
    void *value;
    struct Node *next; // self-reference
} Node;

// Group elements in list. Equivalent elements (for which equivalent is true) are put
// in the same group. The result is a list of groups. Each group is itself a list.
// Each group contains items that are equivalent.

Node *group_list(Node *list, EqualFun equivalent) {
    
    Node *list_new = malloc(sizeof(Node));
    //list_new = NULL;
    list_new->next = NULL;
    (Node *)list_new->value = malloc(sizeof(Node));
    (char *)(list_new->value->value) = list->value;
    list_new->value->next = NULL;
    Node *temp1 = list->next;
    
    Node *list_tester1 = list_new;
    Node *list_tester2 = list_new;
    
    while (list_new != NULL) {
        
        while (temp1 != NULL) {  //for the list inside list_new
            list_tester2 = list_tester1;
            if (equivalent(list_new->value->value, temp1->value)) {
                list_new->value = append_list(list_new->value, temp1->value);
            } else {     
                while (list_tester2 != NULL) { // for outer list
                    if (!equivalent(list_tester2->value->value, temp1->value)) {
                        list_new = append_list(list_new->value, temp1->value);
                        list_new = append_list(list_tester2->value, temp1->value);
                        list_new = append_list(list_tester1->value, temp1->value);       
                    }        
                    list_tester2 = list_tester2->next;   
                }
            }
            list_new = list_new->next;
        }
    }
    return list_new;
}

标签: clistrecursioncastingvoid-pointers

解决方案


如果在编译时知道最大字长(以及因此子列表的最大数量),您可以创建一个指向各个子列表头部的指针数组。数组的第一个元素将指向长度为 1 的单词的子列表,数组的第二个元素将指向长度为 2 的单词的子列表,依此类推。

如果您想要一个链表的链表(即嵌套链表),那么您将必须创建两种类型的节点。一种类型的节点将用于主链表,一种类型的节点将用于子链表。

例如,您可以定义以下两个结构:

struct SubListNode
{
    char *word;
    struct SubListNode *next;
};

struct MainListNode
{
    struct SubListNode *head_of_sublist;
    struct MainListNode *next;
};

在这种情况下,我认为没有理由使用 void 指针,因为引用对象的类型始终是已知的。

尽管两个列表可以struct通过使用 void 指针共享相同的内容,因此您只需声明一个struct,但我认为这样做没有任何好处。每当取消引用 void 指针时,您都必须将其转换为它指向的适当类型。这将使您的代码比简单地声明第二种类型的struct.


推荐阅读