我试图反转"信息"列表中的字段如下面的
struct nodo {
int info;
struct nodo *next;
struct nodo *prev;
} ;
typedef struct nodo nodo;
这是主要的,两个输出应该是n个mebmers的原始列表,以及倒排列表(第一个值是n,第二个是n-1等等)
int main(int argc, const char * argv[]) {
struct nodo *p;
p = CreateList();
PrintList(p);
IvertList(p);
Printlist(p);
return 0;
}
这里是InvertList():( Count()函数只返回列表的维度,我知道它是一个混乱的方式,但我现在专注于结果)
void InvertList (struct nodo *p) {
int tmp = 0, num = 0, i = 0;
num = (Count(p));
tmp = num;
for (i=1; i!=tmp; i++) {
Swap(p,num);
num--;
}
}
这里是Swap(),这应该将值(int info)带到列表的第一个位置,到最后一次交换:
void Swap (struct nodo *p, int n) {
int *tmp1 = NULL, *tmp2 = NULL;
int i;
for ( i = 1; i != n && p != NULL; i++) {
tmp1 = &p->info;
p = p->succ;
tmp2 = &p->info;
p->info = *tmp1;
p->prec->info = *tmp2;
}
}
现在打印的输出是:
Value: 1
Value: 2
Value: 3
Value: 4
Value: 5
Value: 1
Value: 1
Value: 1
Value: 1
Value: 1
最后5个值应为5-4-3-2-1。
答案 0 :(得分:1)
您的代码中的错误无法承受,您根本没有撤销您的实际列表,我可以全部保证,但这首先是练习的重点。
链接列表的反转意味着所有指针都切换方向,旧尾部成为新的头部。您似乎正在避免这种情况,而是尝试交换节点信息值。
使用简单的指针交换反转列表:
// note head pointer passed by address
void InvertList(node **pp)
{
node *cur = *pp;
while (cur)
{
node *tmp = cur->prev;
cur->prev = cur->next;
cur->next = tmp;
*pp = cur;
cur = cur->prev;
}
}
从main()
调用:
InvertList(&p);
请注意无需交换,复制等信息值节点指针只需切换方向,其枚举将从另一端开始。完整的工作示例如下所示:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int info;
struct node *next;
struct node *prev;
};
typedef struct node node;
static void PrintList(const node *head)
{
while (head)
{
printf("%d: this=%p, prev=%p, next=%p\n",
head->info, head, head->prev, head->next);
head = head->next;
}
}
static void InvertList(node **pp)
{
node *cur = *pp;
while (cur)
{
node *tmp = cur->prev;
cur->prev = cur->next;
cur->next = tmp;
*pp = cur;
cur = cur->prev;
}
}
int main()
{
node *prev = NULL, *head = NULL, **pp = &head;
for (int i=1; i<=5; ++i)
{
*pp = malloc(sizeof **pp);
(*pp)->info = i;
(*pp)->prev = prev;
prev = *pp;
pp = &(*pp)->next;
}
*pp = NULL;
PrintList(head); // prints 1,2,3,4,5
InvertList(&head);
PrintList(head); // prints 5,4,3,2,1
}
输出(地址因此而异)
1: this=0x1001054b0, prev=0x0, next=0x1001054d0
2: this=0x1001054d0, prev=0x1001054b0, next=0x1001054f0
3: this=0x1001054f0, prev=0x1001054d0, next=0x100105510
4: this=0x100105510, prev=0x1001054f0, next=0x100105530
5: this=0x100105530, prev=0x100105510, next=0x0
5: this=0x100105530, prev=0x0, next=0x100105510
4: this=0x100105510, prev=0x100105530, next=0x1001054f0
3: this=0x1001054f0, prev=0x100105510, next=0x1001054d0
2: this=0x1001054d0, prev=0x1001054f0, next=0x1001054b0
1: this=0x1001054b0, prev=0x1001054d0, next=0x0
答案 1 :(得分:0)
您的Swap
fcn:
p->info = *tmp1;
p->prev->info = *tmp2;
但那时tmp1
和tmp2
是什么?好吧,在我们提升p
后,tmp1
指向p->prev->info
,而tmp2 = &p->info;
因此我们可以将这些作业重写为:
p->info = p->prev->info;
p->prev->info = p->info;
所以,我们可以再次重写它们,实际上是:
p->info = p->prev->info;
p->prev->info = p->prev->info;
因此,第二项任务不会改变任何有效的内容。因此,Swap
中InvertList
的第一次调用将获取第一个元素(1)的值,并将列表中的所有值设置为等于它。随后对Swap
的调用行为相似但不起作用,因为列表已包含所有1个。
以下是重写Swap
的简单方法:
void Swap(struct nodo *p, int n)
{
if (n <= 1)
return;
int tmp = p->info;
for (int i = 1; i != n; ++i, p = p->next)
p->info = p->next->info;
p->info = tmp;
}
但请注意,您撰写InvertList
的方式正在进行theta(n ^ 2)工作。第一循环迭代移位第一元素n-1个点,第二个迭代移位第一个元素n-2个点,第三个迭代移位第一个元素n-3个点,依此类推,向下移动第一个元素1个点。所以,你最终会做出类似n *(n - 1)/ 2总转换的事情来反转列表。
链接列表可以在theta(n)工作中反转/反转。看看你是否能找到更好的方法来做到这一点。如果你有一个指向列表开头和结尾的指针(你经常想要它),那么你可以做一些类似于反转字符串中字符的东西,例如。