如何从 C 中的列表创建交替子列表?
How to Create Alternating Sub List from List in C?
假设我有一个具有以下结构的链表:
typedef struct _Node {
int value;
struct _Node *next;
} Node;
3 -> 0 -> 4 -> 5 -> 3 -> 2 -> 1 -> 11 -> NULL
我的目标是将其变成一个由不同子列表交替排列的大列表。
这是本质上是“列表列表”的结构:
typedef struct _List {
Node *node;
struct _List *next;
} List;
我的最终目标是创建一个看起来像这样的东西:
// [] denotes a sub list not an array
[3 -> 5 -> 1 - > NULL] -> [0 -> 3 -> 11 -> NULL] -> [4 -> 2 -> NULL]
我已经创建了包含节点的列表和由另外 2 个列表组成的列表结构。我已经尝试实现一个能够产生这个的序列,但是,在找到要放入新子列表的 nTh 节点后,我很挣扎,我如何更改它的 next 以指向正确的新 nTh 节点。
例如:假设我有一个较小的链表:1 -> 5 -> 8 -> 10 -> NULL
当我将 1
添加到我的第一个子列表时,它仍将指向 5,而后者仍指向 8,依此类推。我的实际目标是让 1 现在指向 8,8 指向 NULL,然后在第二个子列表中,5 指向 10,10 指向 NULL。
我拥有的以下代码具有我想要的正确序列并以这种方式打印,但是,我已经能够为链表创建创建正确的代码。是否有任何方法或功能有助于实现此解决方案?
Node * list; // suppose that the head has a value of 3 which points to 0 and so on
List * bigList; // suppose that bigList points to 2 other lists in
bigList -> node = list; // first node in first list points to the node list (3)
k = 3; // sub-lists that are created
size = 8; // number of nodes in the linked list
for(int i = 0; i < k; i++){
for(int j = i; j < size; j += k){
// here is where I would have to manipulate list and weave it into different sub lists
fprintf(stdout, "%d -> ", getNode(list, j) -> value); // prints correct sequence (getNode is a function that finds the nTh node in the list)
}
fprintf(stdout, "\n");
}
您应该插入 current 列表,而不是总是插入第一个列表,并在每次插入后更新它以指向下一个列表。使用额外的指针很容易实现:
void insert_node_into_list (Node ** list, int value) {
Node * node = malloc(sizeof *node);
*node = (Node) {.value = value, .next = NULL};
while (*list) list = &(**list).next;
*list = node;
}
void new_list (List ** superlist) {
// since we're creating all superlists at once, they can be inserted in any order
// so we do it at the front, since it's faster
List * list = malloc(sizeof *list);
*list = (List) {.node = NULL, .next = *superlist};
*superlist = list;
}
void insert_node_into_superlist (List * superlist, List ** current, int value) {
insert_node_into_list(&(**current).node, value);
*current = (**current).next;
if (!*current) *current = superlist;
}
现在您只需像这样构建您的列表:
List * superlist = NULL;
unsigned x;
for (x = 0; x < 3; x ++) new_list(&superlist);
List * current = superlist;
insert_node_into_superlist(superlist, ¤t, 3);
insert_node_into_superlist(superlist, ¤t, 0);
insert_node_into_superlist(superlist, ¤t, 4);
insert_node_into_superlist(superlist, ¤t, 5);
insert_node_into_superlist(superlist, ¤t, 3);
insert_node_into_superlist(superlist, ¤t, 2);
insert_node_into_superlist(superlist, ¤t, 1);
insert_node_into_superlist(superlist, ¤t, 11);
current
指针将始终指向下一个用于插入的子列表,因此它将遍历超级列表中的所有子列表。由于它在到达末尾时(通过 if (!*current) *current = superlist;
行)重置为超级列表的开头,因此这确保了值以旋转方式插入到每个子列表中。
假设我有一个具有以下结构的链表:
typedef struct _Node {
int value;
struct _Node *next;
} Node;
3 -> 0 -> 4 -> 5 -> 3 -> 2 -> 1 -> 11 -> NULL
我的目标是将其变成一个由不同子列表交替排列的大列表。
这是本质上是“列表列表”的结构:
typedef struct _List {
Node *node;
struct _List *next;
} List;
我的最终目标是创建一个看起来像这样的东西:
// [] denotes a sub list not an array
[3 -> 5 -> 1 - > NULL] -> [0 -> 3 -> 11 -> NULL] -> [4 -> 2 -> NULL]
我已经创建了包含节点的列表和由另外 2 个列表组成的列表结构。我已经尝试实现一个能够产生这个的序列,但是,在找到要放入新子列表的 nTh 节点后,我很挣扎,我如何更改它的 next 以指向正确的新 nTh 节点。
例如:假设我有一个较小的链表:1 -> 5 -> 8 -> 10 -> NULL
当我将 1
添加到我的第一个子列表时,它仍将指向 5,而后者仍指向 8,依此类推。我的实际目标是让 1 现在指向 8,8 指向 NULL,然后在第二个子列表中,5 指向 10,10 指向 NULL。
我拥有的以下代码具有我想要的正确序列并以这种方式打印,但是,我已经能够为链表创建创建正确的代码。是否有任何方法或功能有助于实现此解决方案?
Node * list; // suppose that the head has a value of 3 which points to 0 and so on
List * bigList; // suppose that bigList points to 2 other lists in
bigList -> node = list; // first node in first list points to the node list (3)
k = 3; // sub-lists that are created
size = 8; // number of nodes in the linked list
for(int i = 0; i < k; i++){
for(int j = i; j < size; j += k){
// here is where I would have to manipulate list and weave it into different sub lists
fprintf(stdout, "%d -> ", getNode(list, j) -> value); // prints correct sequence (getNode is a function that finds the nTh node in the list)
}
fprintf(stdout, "\n");
}
您应该插入 current 列表,而不是总是插入第一个列表,并在每次插入后更新它以指向下一个列表。使用额外的指针很容易实现:
void insert_node_into_list (Node ** list, int value) {
Node * node = malloc(sizeof *node);
*node = (Node) {.value = value, .next = NULL};
while (*list) list = &(**list).next;
*list = node;
}
void new_list (List ** superlist) {
// since we're creating all superlists at once, they can be inserted in any order
// so we do it at the front, since it's faster
List * list = malloc(sizeof *list);
*list = (List) {.node = NULL, .next = *superlist};
*superlist = list;
}
void insert_node_into_superlist (List * superlist, List ** current, int value) {
insert_node_into_list(&(**current).node, value);
*current = (**current).next;
if (!*current) *current = superlist;
}
现在您只需像这样构建您的列表:
List * superlist = NULL;
unsigned x;
for (x = 0; x < 3; x ++) new_list(&superlist);
List * current = superlist;
insert_node_into_superlist(superlist, ¤t, 3);
insert_node_into_superlist(superlist, ¤t, 0);
insert_node_into_superlist(superlist, ¤t, 4);
insert_node_into_superlist(superlist, ¤t, 5);
insert_node_into_superlist(superlist, ¤t, 3);
insert_node_into_superlist(superlist, ¤t, 2);
insert_node_into_superlist(superlist, ¤t, 1);
insert_node_into_superlist(superlist, ¤t, 11);
current
指针将始终指向下一个用于插入的子列表,因此它将遍历超级列表中的所有子列表。由于它在到达末尾时(通过 if (!*current) *current = superlist;
行)重置为超级列表的开头,因此这确保了值以旋转方式插入到每个子列表中。