我正在尝试实现一个交换双链表的两个节点的函数,以便对当前目录的内容进行排序。但我的功能似乎是“删除”我的列表中的一些元素,这里是代码:
void node_swap(struct s_node *left, struct s_node *right)
{
struct s_node *tmp;
tmp = left->prev;
if (tmp)
{
tmp->next = right;
right->prev = tmp;
}
else
right->prev = NULL;
left->prev = right;
left->next = right->next;
right->next = left;
right->next->prev = left->prev;
}
我看不出这有什么问题?
答案 0 :(得分:2)
说这是您的初始结构TMP -> L -> R -> X
您没有正确更新X-> prev。在您的最后一行right->next->prev = left->prev;
右 - >接下来是左边。所以你要更新左边的prev,这是错误的。相反,你应该做
if(left->next != null)
left->next(which is X)->prev = left
所以,我认为这将有效
void node_swap(struct s_node *left, struct s_node *right)
{
struct s_node *tmp;
tmp = left->prev;
if (tmp)
tmp->next = right;
right->prev = tmp;
left->prev = right;
left->next = right->next;
right->next = left;
if(left->next != null)
left->next(which is X)->prev = left
}
答案 1 :(得分:1)
从问题中发布的代码中,我推断出您的函数假设您正在交换相邻节点。
尝试以下方法:
if ( left->prev )
left->prev->next = right;
if ( right->next )
right->next->prev = left;
left->next = right->next;
right->prev = left->prev;
right->next = left;
left->prev = right;
编辑:在原始问题中发表评论后,执行以下操作要快得多:
char* tmpName = right->name;
right->name = left->name;
left->name = tmpName;
答案 2 :(得分:1)
如果你写下你想做的事,你就可以实现一个非常简单直接的解决方案。
[[工作代码在答案的最后]]
例如,如果您想要交换两个节点(比如A和B),则根据节点的位置有两个可能性。他们可能相邻或不相邻。
在相邻的情况下,你可以写:
[X] - [A] - [B] - [Y]
A->prev = X;
A->next = B;
B->prev = A;
B->next = Y;
如果你将A与B交换,你将最终得到:
[X] - [B] - [A] - [Y]
A->prev = B;
A->next = Y;
B->prev = X;
B->next = A;
这是你想要的。您必须重新排列指针以交换两个节点A和B.
如果使用矩阵形式,规则将更直观:
A B A B
prev X A => prev B X
next B Y next Y A
或者只是单独编写矩阵:
X A --\ B X
B Y --/ Y A
请注意,交换矩阵顺时针旋转90度。如果索引矩阵中的元素,则可以组成一个分配表:
0 1 --\ 2 0
2 3 --/ 3 1
因此,如果将指针存储在数组中,则可以轻松地重新排列它们:
0,1,2,3 -> 2,0,3,1
您也可以为不相邻的案例制定类似的规则:
[W] - [A] - [X] - ... - [Y] - [B] - [Z]
A->prev = W;
A->next = X;
B->prev = Y;
B->next = Z;
与B交换A:
[W] - [B] - [X] - ... - [Y] - [A] - [Z]
A->prev = Y;
A->next = Z;
B->prev = W;
B->next = X;
A B A B
prev W Y => prev Y W
next X Z next Z X
W Y --\ Y W
X Z --/ Z X
0 1 --\ 1 0
2 3 --/ 3 2
0,1,2,3 -> 1,0,3,2
因为我们正在处理链表,所以仅更改特定节点中的指针是不够的。我们必须更新指向我们想要交换的节点的指针。该指针位于可交换对象的邻域中。
请注意,位于我们的指针所指向的节点中的指针总是指向我们自己。
A->prev->next = A
A->next->prev = A
因此,在根据关联规则更新指针后,您只需将外部指针指向给定节点,就完成了!请确保邻居当然存在。
您还需要检查节点A是否在节点B之前链接。如果不是,则需要交换这两个参数。感谢kralyk提醒。
这足以写出进行交换的必要函数。
int areTheyNeighbours(Node A,Node B) {
return ( A->next == B && B->prev == A ) || ( A->prev == B && B->next == A );
}
void refreshOuterPointers(Node A) {
if (A->prev != NULL)
A->prev->next = A;
if (A->next != NULL)
A->next->prev = A;
}
void swap(Node A,Node B) {
Node swapperVector[4];
Node temp;
if (A == B) return;
if (B->next == A) {
temp = A;
A = B;
B = temp;
}
swapperVector[0] = A->prev;
swapperVector[1] = B->prev;
swapperVector[2] = A->next;
swapperVector[3] = B->next;
if (areTheyNeighbours(A,B)) {
A->prev = swapperVector[2];
B->prev = swapperVector[0];
A->next = swapperVector[3];
B->next = swapperVector[1];
} else {
A->prev = swapperVector[1];
B->prev = swapperVector[0];
A->next = swapperVector[3];
B->next = swapperVector[2];
}
refreshOuterPointers(A);
refreshOuterPointers(B);
}
以下程序的输入:
Initial state: [1]-[2]-[3]-[4]
--------------------------------
[1] <-> [2]: [2]-[1]-[3]-[4]
[1] <-> [2]: [1]-[2]-[3]-[4]
[2] <-> [1]: [2]-[1]-[3]-[4]
[2] <-> [1]: [1]-[2]-[3]-[4]
--------------------------------
[1] <-> [3]: [3]-[2]-[1]-[4]
[1] <-> [3]: [1]-[2]-[3]-[4]
[3] <-> [1]: [3]-[2]-[1]-[4]
[3] <-> [1]: [1]-[2]-[3]-[4]
--------------------------------
[1] <-> [4]: [4]-[2]-[3]-[1]
[1] <-> [4]: [1]-[2]-[3]-[4]
[4] <-> [1]: [4]-[2]-[3]-[1]
[4] <-> [1]: [1]-[2]-[3]-[4]
--------------------------------
[2] <-> [3]: [1]-[3]-[2]-[4]
[2] <-> [3]: [1]-[2]-[3]-[4]
[3] <-> [2]: [1]-[3]-[2]-[4]
[3] <-> [2]: [1]-[2]-[3]-[4]
--------------------------------
[2] <-> [4]: [1]-[4]-[3]-[2]
[2] <-> [4]: [1]-[2]-[3]-[4]
[4] <-> [2]: [1]-[4]-[3]-[2]
[4] <-> [2]: [1]-[2]-[3]-[4]
--------------------------------
[3] <-> [4]: [1]-[2]-[4]-[3]
[3] <-> [4]: [1]-[2]-[3]-[4]
[4] <-> [3]: [1]-[2]-[4]-[3]
[4] <-> [3]: [1]-[2]-[3]-[4]
您可以通过以下链接在一秒钟内运行代码:
http://codepad.org/UHcmmag1
使用更正的交换功能更新了链接:http://codepad.org/LbRYjvPr
#include <stdio.h>
#include <stdlib.h>
typedef struct node_v {
int id;
struct node_v* prev;
struct node_v* next;
} Node_v;
typedef Node_v* Node;
void print(Node node) {
while (node->prev != NULL)
node = node->prev;
printf(" [%d]",node->id);
while (node->next != NULL) {
node = node->next;
printf("-[%d]",node->id);
}
printf("\n");
}
void connect(Node first,Node second) {
first->next = second;
second->prev = first;
}
Node createNode(int id) {
Node node = (Node)malloc(sizeof(Node_v));
node->id = id;
node->prev = NULL;
node->next = NULL;
return node;
}
int areTheyNeighbours(Node A,Node B) {
return ( A->next == B && B->prev == A ) || ( A->prev == B && B->next == A );
}
void refreshOuterPointers(Node A) {
if (A->prev != NULL)
A->prev->next = A;
if (A->next != NULL)
A->next->prev = A;
}
void swap(Node A,Node B) {
Node swapperVector[4];
Node temp;
if (A == B) return;
if (B->next == A) {
temp = A;
A = B;
B = temp;
}
swapperVector[0] = A->prev;
swapperVector[1] = B->prev;
swapperVector[2] = A->next;
swapperVector[3] = B->next;
if (areTheyNeighbours(A,B)) {
A->prev = swapperVector[2];
B->prev = swapperVector[0];
A->next = swapperVector[3];
B->next = swapperVector[1];
} else {
A->prev = swapperVector[1];
B->prev = swapperVector[0];
A->next = swapperVector[3];
B->next = swapperVector[2];
}
refreshOuterPointers(A);
refreshOuterPointers(B);
}
int main() {
Node n1 = createNode(1);
Node n2 = createNode(2);
Node n3 = createNode(3);
Node n4 = createNode(4);
connect(n1,n2);
connect(n2,n3);
connect(n3,n4);
printf("\nInitial state:");
print(n2);
printf("--------------------------------\n");
printf("[1] <-> [2]: ");
swap(n1, n2);
print(n1);
printf("[1] <-> [2]: ");
swap(n1, n2);
print(n1);
printf("[2] <-> [1]: ");
swap(n2, n1);
print(n1);
printf("[2] <-> [1]: ");
swap(n2, n1);
print(n1);
printf("--------------------------------\n");
printf("[1] <-> [3]: ");
swap(n1, n3);
print(n2);
printf("[1] <-> [3]: ");
swap(n1, n3);
print(n2);
printf("[3] <-> [1]: ");
swap(n3, n1);
print(n2);
printf("[3] <-> [1]: ");
swap(n3, n1);
print(n2);
printf("--------------------------------\n");
printf("[1] <-> [4]: ");
swap(n1, n4);
print(n3);
printf("[1] <-> [4]: ");
swap(n1, n4);
print(n3);
printf("[4] <-> [1]: ");
swap(n4, n1);
print(n3);
printf("[4] <-> [1]: ");
swap(n4, n1);
print(n3);
printf("--------------------------------\n");
printf("[2] <-> [3]: ");
swap(n2, n3);
print(n3);
printf("[2] <-> [3]: ");
swap(n2, n3);
print(n3);
printf("[3] <-> [2]: ");
swap(n3, n2);
print(n3);
printf("[3] <-> [2]: ");
swap(n3, n2);
print(n3);
printf("--------------------------------\n");
printf("[2] <-> [4]: ");
swap(n2, n4);
print(n3);
printf("[2] <-> [4]: ");
swap(n2, n4);
print(n3);
printf("[4] <-> [2]: ");
swap(n4, n2);
print(n3);
printf("[4] <-> [2]: ");
swap(n4, n2);
print(n3);
printf("--------------------------------\n");
printf("[3] <-> [4]: ");
swap(n3, n4);
print(n4);
printf("[3] <-> [4]: ");
swap(n3, n4);
print(n4);
printf("[4] <-> [3]: ");
swap(n4, n3);
print(n4);
printf("[4] <-> [3]: ");
swap(n4, n3);
print(n4);
printf("--------------------------------\n");
return 0;
}
答案 3 :(得分:0)
非常短的代码非常有效,花费了2个小时:
您需要交换两个节点......
static inline void swap_list(t_lst **lst)
{
t_lst *tmp;
if ((*lst)->next) // you need to make sure you have at least 2 items in your list
{
tmp = *lst; // let's store 1st node's address, that will become the second one after the swap
*lst = (*lst)->next; // Reversely our 2nd one will become the 1st one after the swap. It also allows us to set the beginning of our list.
/*
** Now you need to work on the 6 links that exist : between the last elem (that may be the 2nd one)
** and the 1st one you have 2 links (next and prev), same between the 1st one
** and the 2nd one (2 links again) and finally 2 links between the 2nd one
** and the 3d one (that may be the first node)
*/
tmp->next = (*lst)->next; // tmp will have second position and needs to point to the third elem. Since *lst is now (*lst)->next, here we refer to the 3rd elem.
tmp->next->prev = tmp; // we have then to tell this third elem where stands the second one with this line.
(*lst)->prev = tmp->prev; // before destroying the link to last node that tmp contains, we assign it to the future 1st elem of our list
tmp->prev = *lst; // now we can safely tell the second node its link to the first.
(*lst)->next = tmp; // and reversely tells where is the second elem after the first.
(*lst)->prev->next = *lst; // finally we tell the last node where it the first one.
}
}
我希望它可以提供帮助。
ps:万一你想知道:
typedef struct s_lst
{
void *data; // or a more specific type if you wish
struct s_lst *prev;
struct s_lst *next;
} t_lst;