如何使用Fibonacci系列动态填充链接列表

时间:2016-04-15 17:37:49

标签: c

我有一个链表,我想填充一个特定的循环号。我在下面的代码中显示了使用C链接列表的Fibonacci系列。

这是我没有任何循环的代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node 
{
    int count;
    int fibo;    
    struct Node* next;

}node;

int
fibo(int val){
        if(val == 1 || val == 2) {
                return 1;
        }
        return fibo(val - 1) + fibo(val - 2);
}

int
main (void)
{
    node f1, f2, f3;

    f1.count = 1;
    f1.fibo = fibo(1);

    f2.count = 2;
    f2.fibo = fibo(2);

    f3.count = 3;
    f3.fibo = fibo(3);

    f1.next = &f2;
    f2.next = &f3;
    f3.next = NULL;


    printf("f1 fibo : %i\n", f1.fibo);
    printf("f2 fibo : %i\n", f2.fibo);
    printf("f3 fibo : %i\n", f3.fibo);

    return (0);
}

现在我想通过循环来做到这一点。我该怎么做?

4 个答案:

答案 0 :(得分:1)

对于这个答案,我将忽略因重新计算所有Fibonacci数字而产生的计算效率问题,直至每次调用fibo(n)时检索到的给定数字。

链接列表通常不是&#34;随机访问&#34;允许您使用索引访问任意元素的数据结构。使用带指针的链接列表时,只需要指向链接列表的 head (第一个元素)。然后,您使用循环遍历每个next链接从头部开始遍历列表。如果列表为空,则 head 通常为NULL。

您可以在此处申请。一种方法(有几种方法)是定义一个分配和设置单个条目的函数:

node *set_fibo(int n)
{
    node *fibo_entry = malloc(sizeof(node));

    if ( fibo_entry == NULL ) {
        // error
    }

    fibo_entry->count = n;
    fibo_entry->fibo = fibo(n);
    fibo_entry->next = NULL;
    return fibo_entry;
}

然后在你的主要:

node *fibo_list = NULL;
node *last_fibo = NULL;

// Assume n_fibo is the number of Fibonacci numbers you want to store in order
for ( int n = 1; n <= n_fibo; n++ ) {
    if ( n == 1 )
        fibo_list = last_fibo = set_fibo(1);
    else {
        last_fibo->next = set_fibo(n);
        last_fibo = last_fibo->next;
    }
}

答案 1 :(得分:1)

虽然问题已经得到解答,但我想补充一些关于代码效率方面的内容。如前所述,您不必从头开始计算fibo值,因为您将最新结果保存在单链表中。 因此,如果您有以下列表1-1-2-3-5-,则可以通过简单地添加两个元素(即35)的fibo值来轻松计算新节点的fibo值。因此,新节点的fibo值的值应为8

给定指向倒数第二个元素的指针,此函数将添加一个新节点到列表并设置正确的fibo值:

void addNode(struct Node* node){
    struct Node* n = malloc(sizeof(struct Node));
    n->next = NULL;
    n->count = node->next->count + 1;
    n->fibo = node->fibo + node->next->fibo;    
    node->next->next = n;
}

要使用此功能,您必须在列表中创建前两个节点:

struct Node* n2 = malloc(sizeof(struct Node));
n2->count = 2;
n2->fibo = 1;
n2->next = NULL;
struct Node* n1 = malloc(sizeof(struct Node));
n1->count = 1;
n1->fibo = 1;
n1->next = n2;

如果你现在想要添加 - 比方说10 - 新节点,你只需:

struct Node* ptr = n1;
int i;
for(i=0; i<10;i++) {
    addNode(ptr);
    ptr = ptr->next;
}

如果您现在要打印列表中所有节点的条目,只需遍历列表,直至到达NULL

ptr = n1;
while(ptr != NULL) {
    printf("fib(%d) = %d\n ", ptr->count, ptr->fibo);
    ptr = ptr->next;
}

请记住,您必须手动释放动态分配的项目!

答案 2 :(得分:0)

在您的示例中,节点是main中的自动变量。它们不是动态分配的,只要您不从main返回,它们就会存在。您可以使用自动节点数组扩展此概念:

#include <stdio.h>
#include <stdlib.h

typedef struct Node Node;

struct Node {
    int count;
    int fibo;    
    Node* next;
};

#define N 30

int main (void)
{
    Node fibo[N];
    Node *head = NULL;
    Node **p = &head;

    int f1 = 0;
    int f2 = 0;

    for (size_t i = 0; i < N; i++) {
        Node *nd = &fibo[i];

        nd->count = i + 1;
        nd->fibo = f2 + f1 ? f2 + f1 : 1;

        f1 = f2;
        f2 = nd->fibo;

        *p = nd;
        p = &(*p)->next;
    }
    *p = NULL;

    Node *nd = head;

    while (nd) {
        printf("fib(%d) == %d\n", nd->count, nd->fibo);
        nd = nd->next;
    }

    return (0);
}

但是,为什么你需要斐波纳契系列作为链表,目前尚不清楚。还有一句警告:不要在列表中混合堆栈上的节点(如此处)和堆上的节点(如潜伏者的答案)。这个答案只是将你的答案扩展到许多节点,而潜伏者的答案显示了链接列表的更一般概念。

答案 3 :(得分:0)

以下是我认为你可以做到的。您可以为节点使用数组。

node f[3];
int i;

for ( i = 0 ; i < 3 ; i++ )
{
    f[i].count = i+1;
    f[i].fibo = fibo (i+1);
    if ( i == 2 )
    {   
        f[i].next = NULL;
    }
    else
    {
        f[i].next = &f[i+1];
    }
}