交换链表项目问题C.

时间:2015-03-22 18:47:38

标签: c list pointers swap

我试图反转"信息"列表中的字段如下面的

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。

2 个答案:

答案 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;

但那时tmp1tmp2是什么?好吧,在我们提升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; 

因此,第二项任务不会改变任何有效的内容。因此,SwapInvertList的第一次调用将获取第一个元素(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)工作中反转/反转。看看你是否能找到更好的方法来做到这一点。如果你有一个指向列表开头和结尾的指针(你经常想要它),那么你可以做一些类似于反转字符串中字符的东西,例如。