在参数不灵活的情况下更改链表的值

Changing value of Linked List without flexiblility in parameters

我有一个任务。我获得了无法修改的函数声明。

函数声明是 void Insert (Item x, int p, List *L); 我应该在其中更改链表结构 L 的值。

现在,在我的主函数中调用该方法的代码是

struct List *L = malloc(sizeof(List));   
Insert(x,p,L);

我如何更改我的代码以便我可以传递结构列表的地址而不是制作它的另一个副本?

正如我所说,我根本无法更改函数声明。

/********************************************************************* * FUNCTION NAME: Insert * PURPOSE: Inserts an Item in a List. * ARGUMENTS: . The Item to be inserted (Item) * . The position in the List * where the Item should be inserted in (int) * . The address of the List (List *L) * REQUIRES (preconditions): * . The position should be a nonnegative integer * not greater than the size of the List. * . The List should not be full. * ENSURES: . Empty will return false (0). * . Size will return the first integer greater * than the size of the List before the call. * . Peek in the same position will find * the Item that was inserted. *********************************************************************/ extern void Insert (Item X, int position, List *L);

我试过但没有用的是 head->next = L; //changing the next item in list to L L = head; //changing the address of L so it remains the head of the list

您可能想查看 C 中地址和指针之间的区别(或相似之处),因为您的问题的答案是您已经传递了结构列表的地址。

我会试着解释一下。 malloc() returns 内存地址,又名指针,在 struct List *L 中用 * 符号表示。当我在脑海中读到这一行时,我会说 "L contains a pointer to a struct List object" 或 "L contains the memory address of a struct List object".

所以在那种情况下,当您编写 Insert(L, x) 时,您已经传递了一个指向结构列表对象的指针。并且没有制作其他副本。因此,您在 Insert() 函数中执行的任何操作都将作用于原始列表。

此规则的唯一例外是如果您尝试在插入方法中重新分配 L,如下所示:

void Insert(struct List* L, int x) {
    L = NULL; // or L = malloc(sizeof(struct List));
}

这不会像您预期的那样,但其原因更复杂,您可能暂时不需要知道。

你的函数声明有问题。

您的代码表明您有一个具有以下签名的函数:

void Insert (struct List *L, int x);

您链接的头文件使用带有此签名的函数插入:

extern void Insert (Item X, int position, List *L); 

注意附加参数 Item X

没有太多内容可以继续,因为您没有向我们展示您的大部分代码,但我建议您看一下您缺少的参数。

我认为这会起作用:

void Insert (Item x, int p, List *L) {
    struct List newnode, last = *L;
    newnode = (struct List)malloc(sizeof(struct List));
    newnode->item = x;
    newnode->next = NULL;
    if (last == NULL){
        if (p == 0) { *L = newnode; }//first node
        else { printf("List is empty and index %d does not exist", p); }
    } else if (p == 0) {
        newnode->next = *L;
        *L = newnode;
    }
    else{
        int counter = 0;
        while (1) {
            if (counter == p) {
                newnode->next = last->next; 
                last->next = newnode;
                break;
            }
            last = last->next;
            counter++;
            if (last->next == NULL && counter != p){ break; }
        }
    }
}

首先:

How would I change my code so I can pass the address of the struct List instead of making another copy of it?

您已经这样做了:void Insert (Item x, int p, List *L); 指针 指向列表结构,而不是结构本身,因此您没有复制它。

其次:

What I tried that didn't work was head->next = L; //changing the next item in list to L L = head; //changing the address of L so it remains the head of the list

不行。在 Insert 函数中,L 是指向 List 的指针的值。因此,如果您在函数内部更改此值,它不会在外部更改,因为 L 的值是通过副本传递的。只会看到对 *L 的更改,因为它们不会更改 L 本身的值,但会更改 L 指向的值。

我可以向你保证,在 Insert 函数中不需要 L = 来完成这个任务。

此外,请仔细查看先决条件 - 他们应该描述你不需要麻烦自己的情况(可能,我不知道创建此任务的人,但我会这样理解) - 意思是,如果用户不遵守它们,那是用户自己的错,任何不好的事情都可能发生。