C 中的反转双链双端队列
我在 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;
}
}
但它似乎不起作用,我已经使用如下所示的双端队列对其进行了测试:1,2,3 输出是:3,这个过程似乎弄乱了数字的实际值。 IE。 2 变成 2.90085e-309...我认为指针切换混乱,但我找不到问题。即使这并不意味着我的代码是正确的;它编译得很好。
I'm having trouble reversing my doublely linked deque list (with only a back sentinel) in C, I'm approaching it by switching the pointers and here is the code I have so far:
/* 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;
}
}
But it doesn't seem to work, I've been testing it with a deque that looks like this: 1, 2, 3
The output is: 3 and this process seems to mess up the actual value of the numbers. ie. 2 becomes 2.90085e-309... I think the pointer switching is messed up but I cannot find the problem. And even though it doesn't mean my code is correct; it compiles fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
像双端队列这样的链接结构很容易进行递归,因此在处理链接结构时我倾向于采用递归风格。这也允许我们增量地编写它,以便我们可以轻松地测试每个函数。像你的函数一样循环有很多缺点:你可以很容易地引入 fencepost 错误 并且它倾向于令人困惑的大函数。
首先,您决定通过交换指针来做到这一点,对吗?因此,编写一个函数来交换指针:
现在,编写一个函数来反转单个节点中的指针:
现在,将其递归地放在一起:
我不确定您的结构体是如何设计的;我的函数假设您的双端队列是循环的,并且您将在哨兵上调用它。
编辑:如果您的双端队列不是循环的,您还需要在哨兵上调用
swapPointersInCirListDeque(q)
,因此将swapPointersInCirListDeque(q)
移到之前>if
语句。如果您打算在此之后使用 backSentinel,您也应该更改它,因为它现在位于列表的前面。如果您有 frontSentinel,则只需将
swapCirListDequePointers(&(q->frontSentinel),&(q->backSentinel));
添加到swapPointersInCirListDeque
即可。否则,您必须将第一个节点与q
一起传递,并将q->backSentinel
设置为该节点。Linked structures like deques lend themselves readily to recursion, so I tend to favor a recursive style when dealing with linked structures. This also allows us to write it incrementally so that we can test each function easily. Looping as your function does has many downsides: you can easily introduce fencepost errors and it tends toward large functions that are confusing.
First, you've decided to do this by swapping the pointers, right? So write a function to swap pointers:
Now, write a function that reverses the pointers in a single node:
Now, put it together recursively:
I'm not sure exactly how your struct is designed; my function assumes that your deque is circular and that you'll be calling this on the sentinel.
EDIT: If your deque isn't circular, you'll want to call
swapPointersInCirListDeque(q)
on the sentinel as well, so moveswapPointersInCirListDeque(q)
before theif
statement.If you plan to use the backSentinel after this, you should change that also, since it's now the front of the list. If you have a frontSentinel, you can just add
swapCirListDequePointers(&(q->frontSentinel),&(q->backSentinel));
toswapPointersInCirListDeque
. Otherwise, you'll have to pass in the first node along withq
and setq->backSentinel
to that.如果它是双向链表,则根本不需要更改任何指针。只需交换有效负载:
如果后哨兵指的是
last
指针(因为没有第一个指针可用),那么您需要向后退一步抛出双端队列才能找到它。然而,很难相信会出现这种情况,因为这将是一个相当低效的双端队列(它应该是一个双端队列)。If it's a doubly linked list, you shouldn't need to change any pointers at all. Just swap over the payloads:
If by back sentinel you mean the
last
pointer (as in no first pointer is available), then you need to step backwards throw the deque to find it. It's hard to believe however that this would be the case since it would be a fairly inefficient deque (which is supposed to be a double ended queue).已经向您提供了一些建议;还有另一种可能性:
并且还假设有两个名为
head
和tail
的变量(目前为全局变量),分别指向双端队列的头部和尾部。至少目前,这不假设任何哨兵——只是用NULL指针来表示列表的结尾。
如果您只是将
int
存储在双端队列中,Paxdiablo 的建议是一个很好的建议(除了创建一个双向链接节点来仅保存int
是一种巨大的浪费)。假设实际上您存储的数据足够大,以使双链接节点有意义,那么您还希望避免不必要地移动该数据,至少作为一般规则。You've been given a couple of suggestions already; here's another possibility:
and also assumes a couple of variables (globals for the moment) named
head
andtail
that point to the head and tail of the deque, respectively.At least for the moment, this does not assume any sentinels -- just NULL pointers to signal the ends of the list.
If you're just storing
int
s in the deque, Paxdiablo's suggestion is a good one (except that creating a doubly-linked node to hold only anint
is a massive waste). Assuming that in reality you were storing something large enough for doubly-linked nodes to make sense, you'd also prefer to avoid moving that data around any more than necessary, at least as a general rule.