我无法在C中反转我的双重链接双端队列表(只有一个后哨),我通过切换指针接近它,这是我到目前为止的代码:
/* Reverse the deque
param: q pointer to the deque
pre: q is not null and q is not empty
post: the deque is reversed
*/
/* reverseCirListDeque */
void reverseCirListDeque(struct cirListDeque *q)
{
struct DLink *back = q->backSentinel;
struct DLink *second = q->backSentinel->prev;
struct DLink *third = q->backSentinel->next;
while (second != q->backSentinel->next){
back->next = second;
third = back->prev;
back->next->prev = back;
back = second;
second = third;
}
}
但它似乎不起作用,我一直在测试它看起来像这样的deque:1,2,3 输出是:3,这个过程似乎弄乱了数字的实际值。即。 2变为2.90085e-309 ...我认为指针切换搞砸了,但我找不到问题。即使这并不意味着我的代码是正确的;编译得很好。
答案 0 :(得分:2)
像deques这样的链接结构很容易递归,所以在处理链接结构时,我倾向于使用递归样式。这也允许我们以递增方式编写它,以便我们可以轻松地测试每个函数。循环,因为你的函数确实存在许多缺点:你可以很容易地引入fencepost errors并且它倾向于使大型函数混乱。
首先,你决定通过交换指针来做到这一点,对吗?所以写一个函数来交换指针:
void swapCirListDequePointers(
struct cirListDeque** left,
struct cirListDeque** right)
{
struct cirListDeque* temp = *left;
*left = *right;
*right = temp;
}
现在,编写一个反转单个节点中指针的函数:
void swapPointersInCirListDeque(struct cirListDeque* q)
{
swapCirListDequePointers(&(q->prev),&(q->next));
}
现在,递归地把它放在一起:
void reverseCirListDeque(struct cirListDeque* q)
{
if(q == q->backSentinel)
return;
swapPointersInCirListDeque(q);
// Leave this call in tail position so that compiler can optimize it
reverseCirListDeque(q->prev); // Tricky; this used to be q->next
}
我不确定你的结构是如何设计的;我的函数假设你的双端队列是循环的,你将在哨兵上调用它。
编辑:如果您的双端队列不是循环播放,您也需要在哨兵号码上拨打swapPointersInCirListDeque(q)
,因此请在swapPointersInCirListDeque(q)
语句前移动if
。
如果您计划在此之后使用backSentinel,您也应该更改它,因为它现在是列表的前面。如果您有frontSentinel,则可以将swapCirListDequePointers(&(q->frontSentinel),&(q->backSentinel));
添加到swapPointersInCirListDeque
。否则,您必须将第一个节点与q
一起传入,并将q->backSentinel
设置为该值。
答案 1 :(得分:1)
如果它是双向链表,则根本不需要更改任何指针。只需交换有效载荷:
pointer1 = first
pointer2 = last
while pointer1 != pointer2 and pointer2->next != pointer1:
temp = pointer1->payload
pointer1->payload = pointer2->payload
pointer2->payload = temp
pointer1 = pointer1->next
pointer2 = pointer2->prev
如果通过后哨兵你的意思是last
指针(因为没有第一个指针可用),那么你需要向后退一步来发现它。然而很难相信这种情况会是这样的,因为它会是一个相当低效的双端队列(它应该是一个双端队列)。
答案 2 :(得分:0)
你已经得到了一些建议;这是另一种可能性:
// Assumes a node something like:
typedef struct node {
struct node *next, *prev;
int data;
} node;
并假设一些名为head
和tail
的变量(目前为全局变量)分别指向双端队列的头部和尾部。
void reverse() {
node *pos = head;
node *temp = pos->next;
head = tail;
tail = pos;
while (pos != NULL) {
node *t = pos->prev;
pos->prev = pos->next;
pos->next = t;
pos = temp;
if (temp)
temp = temp->next;
}
}
至少目前,不假设任何标记 - 只是NULL指针来表示列表的末尾。
如果您只是将int
存储在双端队列中,Paxdiablo的建议是一个很好的建议(除了创建一个双重链接的节点只保留int
是一个巨大的浪费)。假设实际上你存储的东西足够大,以便双链节点有意义,你也更愿意避免移动那些数据,至少作为一般规则。