一个传递结构体指针到函数做修改的问题C语言

题目

img

img

img


不能够实现的代码  对传进来L1 L2结构体指针操作  能够实现让两个链表合并成一个递增的顺序链表 但是L1 L2在Merge函数结束时为NULL 回到main函数却变成了最开始L1 L2的头指针节点


List Merge( List L1, List L2 )
{
    List head,temp;
    head = temp = (List)malloc(sizeof(struct Node));
   
        L1 = L1->Next;
        L2 = L2->Next;


      while(L1 && L2)
     {
        if(L1->Data <= L2->Data)
        {
                temp->Next = L1;
                L1 = L1->Next;
        }
        else
        {
                temp->Next = L2;
                L2 = L2->Next;
        }
        temp = temp->Next;
    }
   
    if(L1)
    {
        while(L1)
        {
            temp->Next = L1;
            L1 = L1->Next;
            temp = temp->Next;
        }
        temp->Next = NULL;
    }
   
    else if(L2)
    {
         while(L2)
        {
            temp->Next = L2;
            L2 = L2->Next;
            temp = temp->Next;
        }
        temp->Next = NULL;
    }
    else
        temp->Next = NULL;

    //到这里L1 L2为NULL 运行到后面在main函数里打印出L1 L2为原始头节点。。


    return head;
}

能够实现的代码 使用两个局部变量来移动节点  用temp来指向产生一个新的链表  最后让L1 L2始终是头节点未改动,L1 L2头结点下一个指向NULL  成功影响外面的main函数里的L1 L2 这是为什么呢?为什么上一段代码不能影响到main函数里的L1 L2 第二段这个确实可以呢?


List Merge( List L1, List L2 )
{
    List head,temp,TL1,TL2;
    head = temp = (List)malloc(sizeof(struct Node));
    
    
        TL1 = L1->Next;
        TL2 = L2->Next;


      while(TL1 && TL2)
     {
        if(TL1->Data <= TL2->Data)
        {
                temp->Next = TL1;
                TL1 = TL1->Next;
        }
        else
        {
                temp->Next = TL2;
                TL2 = TL2->Next;
        }
        temp = temp->Next;
    }
    
    if(TL1)
    {
        while(TL1)
        {
            temp->Next = TL1;
            TL1 = TL1->Next;
            temp = temp->Next;
        }
        temp->Next = NULL;
    }
    
    else if(TL2)
    {
         while(TL2)
        {
            temp->Next = TL2;
            TL2 = TL2->Next;
            temp = temp->Next;
        }
        temp->Next = NULL;
    }
    else
        temp->Next = NULL;

    
L1->Next = NULL;
L2->Next = NULL;

    return head;
}

这个函数这样写,供参考:

List Merge(List L1, List L2)
{
    List  p1 = NULL, p2 = NULL, pL = NULL, L = NULL;
    if (!L1->Next && !L2->Next)
        return NULL;
    L = (List)malloc(sizeof(struct Node));
    L->Next = NULL;
    pL = L;
    p1 = L1->Next;
    L1->Next = NULL;
    p2 = L2->Next;
    L2->Next = NULL;
    while (p1 && p2) {
        if (p1->Data <= p2->Data) {
            pL->Next = p1;
            pL = p1;
            p1 = p1->Next;
        }
        else {
            pL->Next = p2;
            pL = p2;
            p2 = p2->Next;
        }
    }
    pL->Next = p1 ? p1 : p2;
    return L;
}

  • 以下回答由chatgpt基于相关博客总结生成:

    要想让函数中的结构体指针修改后可以影响到主函数中的同名结构体指针,需要将指针作为参数传递给函数,而不是作为局部变量。具体地说,需要将结构体指针的地址作为参数传递给函数,这样函数中对结构体指针进行的修改就会影响到主函数中的同名结构体指针。 以下是修改后的示例代码,其中在merge函数中传递了p和q两个指向结构体指针的指针,这样对它们进行的修改就会影响到主函数中的head1和head2指针。

    #include<stdio.h>
    #include<malloc.h>
    typedef int ElemType;
    typedef struct DNode
    {
        ElemType data;//存放元素值
        struct DNode *prior;//指向前驱结点
        struct DNode *next;//指向后继结点
    }DLinkNode;//双链表的结点类型
    void CreateListF(DLinkNode *&L, ElemType a[], int n)//头插法建立双链表
    {
        DLinkNode *s;
        L = (DLinkNode*)malloc(sizeof(DLinkNode));
        L->next = NULL;
        for (int i = 0; i < n; i++)
        {
            s = (DLinkNode*)malloc(sizeof(DLinkNode));
            s->data = a[i];
            s->next = L->next;
            if (L->next != NULL)
                L->next->prior = s;
            L->next = s;
            s->prior = L;
        }
        s = L->next;
        while (s->next != NULL)
            s = s->next;
        s->next = L;
        L->prior = s;
    }
    void CreateListR(DLinkNode*&L, ElemType a[], int n)//尾插法建立双链表
    {
        DLinkNode *s, *r;
        L = (DLinkNode*)malloc(sizeof(DLinkNode));
        L->next = NULL;
        r = L;
        for (int i = 0; i < n; i++)
        {
            s = (DLinkNode*)malloc(sizeof(DLinkNode));
            s->data = a[i];
            r->next = s;
            s->prior = r;
            r = s;
        }
        r->next = L;
        L->prior = r;
    }
    void InitList(DLinkNode*&L)//初始化线性表
    {
        L = (DLinkNode*)malloc(sizeof(DLinkNode));
        L->prior = L->next = L;
    
    }
    void DestroyList(DLinkNode *&L)//销毁线性表
    {
        DLinkNode *pre = L, *p = pre->next;
        while (p != L)
        {
            free(L);
            pre = p;
            p = pre->next;
        }
        free(pre);
    }
    bool ListEmpty(DLinkNode *L)//判断线性表是否为空
    {
        return(L->next = NULL);
    }
    int ListLength(DLinkNode *L)//求线性表的长度
    {
        DLinkNode *p = L;
        int i = 0;
        while (p->next != L)
        {
            i++;
            p = p->next;
        }
        return i;
    }
    void DispList(DLinkNode *L)//输出线性表
    {
        DLinkNode *p = L->next;
        while (p != L)
        {
            printf("%c", p->data);
            p = p->next;
        }
        printf("\n");
    }
    bool GetElem(DLinkNode *L, int i, ElemType &e)//求线性表第i个元素值
    {
        int j = 1;
        DLinkNode *p = L->next;
        if (i <= 0 || L->next == L)
            return false;
        while (j < i&&p != NULL)
        {
            j++;
            p = p->next;
        }
        if (p == NULL)
            return false;
        else
        {
            e = p->data;
            return true;
        }
    }
    int LocateElem(DLinkNode *L, ElemType e)//查找第一个值域为e的元素序号
    {
        int i = 1;
        DLinkNode *p = L->next;
        while (p != NULL && p->data != e)
        {
            i++;
            p = p->next;
        }
        if (p == NULL)
            return false;
        else
            return i;
    }
    bool ListInsert(DLinkNode *&L, int i, ElemType e)//插入第i个元素
    {
        int j = 0;
        DLinkNode *p = L, *s;
        if (i < 0)
            return false;
        while (j < i - 1 && p != NULL)
        {
            j++;
            p = p->next;
        }
        if (p == NULL)
            return false;
        else
        {
            s = (DLinkNode*)malloc(sizeof(DLinkNode));
            s->data = e;
            s->next = p->next;
            if (p->next != NULL)
                p->next->prior = s;
            s->prior = p;
            p->next = s;
            return true;
        }
    }
    bool ListDelete(DLinkNode*&L, int i, ElemType &e)//删除第i个元素
    {
        int j = 0;
        DLinkNode *p = L, *q;
        if (i <= 0)
            return false;
        while (j < i - 1 && p != NULL)
        {
            j++;
            p = p->next;
        }
        if (p == NULL)
            return false;
        else {
            q = p->next;
            if (q == NULL)
                return false;
            e = q->data;
            p->next = q->next;
            if (p->next != NULL)
                p->next->prior = p;
            free(q);
            return true;
        }
    }
    
    //合并两个链表为递增顺序的链表
    void merge(DLinkNode *&p, DLinkNode *&q) {
        DLinkNode *t1 = p, *t2 = q, *t = NULL;
        while (t1 != NULL && t2 != NULL) {
            if (t1->data < t2->data) {
                t = t1->next;
                t1->next = t2;
                t2->prior = t1;
                t1 = t;
            }
            else {
                t = t2->next;
                t2->next = t1;
                t1->prior = t2;
                t2 = t;
            }
        }
        if (t2 != NULL) {
            p = q;
            q = NULL;
        }
    }
    
    int main()
    {
        DLinkNode *head1, *head2;
        ElemType e;
        printf("双链表的基本运算如下:\n");
        printf(" (1) 初始化双链表head1\n");
        InitList(head1);
        printf(" (2)依次采用尾插法插入a,b,c,d,e元素\n");
        ListInsert(head1, 1, 'a');
        ListInsert(head1, 2, 'b');
        ListInsert(head1, 3, 'c');
        ListInsert(head1, 4, 'd');
        ListInsert(head1, 5, 'e');
        printf(" (3)输出双链表head1:\n");
        DispList(head1);
        printf(" (4)双链表head1长度:%d\n", ListLength(head1));
        printf(" (5)双链表head1为%s\n", (ListEmpty(head1) ? "空" : "非空"));
        GetElem(head1, 3, e);
        printf(" (6)双链表head1的第3个元素:%c\n", e);
        printf(" (7)元素a的位置:%d\n", LocateElem(head1, 'a'));
        printf(" (8)在第4个元素位置上插入f元素\n");
        ListInsert(head1, 4, 'f');
        printf(" (9)输出双链表head1:\n");
        DispList(head1);
        printf(" (10)删除head1的第3个元素\n");
        ListDelete(head1, 3, e);
        printf(" (11)输出双链表head1:\n");
        DispList(head1);
        printf(" (12)初始化双链表head2\n");
        InitList(head2);
        printf(" (13)依次采用尾插法插入k,l,m,n,o元素\n");
        ListInsert(head2, 1, 'k');
        ListInsert(head2, 2, 'l');
        ListInsert(head2, 3, 'm');
        ListInsert(head2, 4, 'n');
        ListInsert(head2, 5, 'o');
        printf(" (14)输出双链表head2:\n");
        DispList(head2);
        printf(" (15)合并双链表head1和head2\n");
        merge(head1, head2);
        printf(" (16)输出双链表head1:\n");
        DispList(head1);
        printf(" (17)释放双链表head1和head2\n");
        DestroyList(head1);
        DestroyList(head2);
        return 1;
    
    }