在双向链表中交换
swap in doubly linked list
我正在尝试交换双向链表中的两个节点。下面是具有交换功能的程序部分。
int swap (int x, int y)
{
struct node *temp = NULL ;
struct node *ptr1, *ptr2;
temp = (struct node *)malloc(sizeof(struct node));
if (head == NULL )
{
printf("Null Nodes");
}
else
{
ptr1 = ptr2 = head;
int count = 1;
while (count != x)
{
ptr1 = ptr1->next;
count++;
}
int count2 = 1;
while (count2 != y)
{
ptr2 = ptr2->next;
count2++;
}
ptr1->next->prev = ptr2;
ptr1->prev->next = ptr2;
ptr2->next->prev = ptr1;
ptr2->prev->next = ptr1;
temp->prev = ptr1->prev;
ptr1->prev = ptr2->prev;
ptr2->prev = temp->prev;
temp->next = ptr1->next;
ptr1->next = ptr2->next;
ptr2->next = temp->next;
}
return 0;
}
当我运行这个程序时,在第一个和第二个节点的情况下,它崩溃了。而对于任何其他节点,它会提供无限循环输出。 (例如:- 2->4 2->4 2->4....等等)`.
我知道还有一些关于节点交换的问题,但我没有找到与我的问题类似的问题。请帮帮我..!!
提前致谢。
如果 ptr1 == head (ptr1->prev == NULL) 或 ptr2 == head (ptr2->prev == NULL),代码将失败,因为它最终会尝试使用 head->next,这是不存在的。如果 ptr1->next == NULL 或 ptr2->next == NULL,也需要检查列表的结尾,这可以使用局部尾指针来处理。使用指向节点指针的指针可以简化代码。例如,指向指向 ptr1 的下一个指针的指针可以是 &ptr1->prev->next 或 &head。指向指向 ptr2 的 prev 指针的指针可以是 &ptr2->next->prev 或 &tail(并设置 tail = ptr2)。
使用指向节点指针的指针解决了交换相邻节点的问题。 temp 也可以是指向节点的指针。
示例代码使用指向节点(而不是计数)的指针进行交换:
typedef struct node NODE;
/* ... */
NODE * SwapNodes(NODE *head, NODE *ptr1, NODE *ptr2)
{
NODE **p1pn; /* & ptr1->prev->next */
NODE **p1np; /* & ptr1->next->prev */
NODE **p2pn; /* & b->prev->next */
NODE **p2np; /* & b->next->prev */
NODE *tail; /* only used when x->next == NULL */
NODE *temp; /* temp */
if(head == NULL || ptr1 == NULL || ptr2 == NULL || ptr1 == ptr2)
return head;
if(head == ptr1)
p1pn = &head;
else
p1pn = &ptr1->prev->next;
if(head == ptr2)
p2pn = &head;
else
p2pn = &ptr2->prev->next;
if(ptr1->next == NULL){
p1np = &tail;
tail = ptr1;
} else
p1np = &ptr1->next->prev;
if(ptr2->next == NULL){
p2np = &tail;
tail = ptr2;
}else
p2np = &ptr2->next->prev;
*p1pn = ptr2;
*p1np = ptr2;
*p2pn = ptr1;
*p2np = ptr1;
temp = ptr1->prev;
ptr1->prev = ptr2->prev;
ptr2->prev = temp;
temp = ptr1->next;
ptr1->next = ptr2->next;
ptr2->next = temp;
return head;
}
这可以压缩,但如果您遇到问题,请详细说明。
typedef struct node Node;
void link( Node* a, Node* b )
{
a->next = b;
b->prev = a;
}
void swap_nodes( Node* a, Node* b )
{
if(a==b) return; // don't swap with yourself
// handle adjacent nodes separately
if( a->next == b )
{
Node* bef = a->prev;
Node* aft = b->next;
link( bef, b); // link bef, b, a, aft
link( b, a );
link( a, aft );
}
else if( b->next == a )
{
Node* bef = b->prev;
Node* aft = a->next;
link( bef, a); // link bef, a, b, aft
link( a, b );
link( b, aft );
}
else
{
Node* a_prv = a->prev;
Node* a_nxt = a->next;
Node* b_prv = b->prev;
Node* b_nxt = b->next;
link( a_prv, b ); link( b, a_nxt ); // links b in a's old position
link( b_prv, a ); link( a, b_nxt ); // links a in b's old position
}
}
另请注意,您的头节点永远不应该是 null
,如果您的列表为空,它应该是一个链接到自身的哨兵节点。这意味着永远没有第一个节点,也没有最后一个节点,列表也永远不会为空。这消除了大量的特殊情况。参见 here
我正在尝试交换双向链表中的两个节点。下面是具有交换功能的程序部分。
int swap (int x, int y)
{
struct node *temp = NULL ;
struct node *ptr1, *ptr2;
temp = (struct node *)malloc(sizeof(struct node));
if (head == NULL )
{
printf("Null Nodes");
}
else
{
ptr1 = ptr2 = head;
int count = 1;
while (count != x)
{
ptr1 = ptr1->next;
count++;
}
int count2 = 1;
while (count2 != y)
{
ptr2 = ptr2->next;
count2++;
}
ptr1->next->prev = ptr2;
ptr1->prev->next = ptr2;
ptr2->next->prev = ptr1;
ptr2->prev->next = ptr1;
temp->prev = ptr1->prev;
ptr1->prev = ptr2->prev;
ptr2->prev = temp->prev;
temp->next = ptr1->next;
ptr1->next = ptr2->next;
ptr2->next = temp->next;
}
return 0;
}
当我运行这个程序时,在第一个和第二个节点的情况下,它崩溃了。而对于任何其他节点,它会提供无限循环输出。 (例如:- 2->4 2->4 2->4....等等)`.
我知道还有一些关于节点交换的问题,但我没有找到与我的问题类似的问题。请帮帮我..!!
提前致谢。
如果 ptr1 == head (ptr1->prev == NULL) 或 ptr2 == head (ptr2->prev == NULL),代码将失败,因为它最终会尝试使用 head->next,这是不存在的。如果 ptr1->next == NULL 或 ptr2->next == NULL,也需要检查列表的结尾,这可以使用局部尾指针来处理。使用指向节点指针的指针可以简化代码。例如,指向指向 ptr1 的下一个指针的指针可以是 &ptr1->prev->next 或 &head。指向指向 ptr2 的 prev 指针的指针可以是 &ptr2->next->prev 或 &tail(并设置 tail = ptr2)。
使用指向节点指针的指针解决了交换相邻节点的问题。 temp 也可以是指向节点的指针。
示例代码使用指向节点(而不是计数)的指针进行交换:
typedef struct node NODE;
/* ... */
NODE * SwapNodes(NODE *head, NODE *ptr1, NODE *ptr2)
{
NODE **p1pn; /* & ptr1->prev->next */
NODE **p1np; /* & ptr1->next->prev */
NODE **p2pn; /* & b->prev->next */
NODE **p2np; /* & b->next->prev */
NODE *tail; /* only used when x->next == NULL */
NODE *temp; /* temp */
if(head == NULL || ptr1 == NULL || ptr2 == NULL || ptr1 == ptr2)
return head;
if(head == ptr1)
p1pn = &head;
else
p1pn = &ptr1->prev->next;
if(head == ptr2)
p2pn = &head;
else
p2pn = &ptr2->prev->next;
if(ptr1->next == NULL){
p1np = &tail;
tail = ptr1;
} else
p1np = &ptr1->next->prev;
if(ptr2->next == NULL){
p2np = &tail;
tail = ptr2;
}else
p2np = &ptr2->next->prev;
*p1pn = ptr2;
*p1np = ptr2;
*p2pn = ptr1;
*p2np = ptr1;
temp = ptr1->prev;
ptr1->prev = ptr2->prev;
ptr2->prev = temp;
temp = ptr1->next;
ptr1->next = ptr2->next;
ptr2->next = temp;
return head;
}
这可以压缩,但如果您遇到问题,请详细说明。
typedef struct node Node;
void link( Node* a, Node* b )
{
a->next = b;
b->prev = a;
}
void swap_nodes( Node* a, Node* b )
{
if(a==b) return; // don't swap with yourself
// handle adjacent nodes separately
if( a->next == b )
{
Node* bef = a->prev;
Node* aft = b->next;
link( bef, b); // link bef, b, a, aft
link( b, a );
link( a, aft );
}
else if( b->next == a )
{
Node* bef = b->prev;
Node* aft = a->next;
link( bef, a); // link bef, a, b, aft
link( a, b );
link( b, aft );
}
else
{
Node* a_prv = a->prev;
Node* a_nxt = a->next;
Node* b_prv = b->prev;
Node* b_nxt = b->next;
link( a_prv, b ); link( b, a_nxt ); // links b in a's old position
link( b_prv, a ); link( a, b_nxt ); // links a in b's old position
}
}
另请注意,您的头节点永远不应该是 null
,如果您的列表为空,它应该是一个链接到自身的哨兵节点。这意味着永远没有第一个节点,也没有最后一个节点,列表也永远不会为空。这消除了大量的特殊情况。参见 here