java - 链表插入函数问题,关于指针指向

查看:117
本文介绍了java - 链表插入函数问题,关于指针指向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

原链表1 2 3。
第一段函数运行正确,插入后为1 2 4 3;
改为第二段代码运行,结果为2 3 4。
问题来了,注意我标出的地方p=(*L);第一段函数我用p做链表元素操作,第二段全替换为(*L)链表元素操作。为什么结果却不同了,如果p是(*L)的指针,结果应该相同;如果(*L)只是给p赋值的话,那么showlist()函数应该显示(*L)原链表而不是修改过的p链表?
我想问题主要是我对p=(*L);的理解不够吧

status Listinsert(Linklist *L,int j,Elemtype e)
{
    Linklist p,r;
    p=(*L);  //
    int i=2;
    r=(Linklist)malloc(sizeof(Node));
    r->data=e;
    r->next=NULL;
    while(i<j)
    {
        i++;
        p=p->next;
    }
    r->next=p->next;
    p->next=r;
    return OK;
}

status Listinsert(Linklist *L,int j,Elemtype e)
{
    Linklist p,r;
    //p=(*L); //下面用(*L)替换p,运行后有问题
    int i=2;
    r=(Linklist)malloc(sizeof(Node));
    r->data=e;
    r->next=NULL;
    while(i<j)
    {
        i++;
        (*L)=(*L)->next; //替换
    }
    r->next=(*L)->next;  //替换
    (*L)->next=r;   
    return OK;
}

////////////////////////////////////////
完整代码

#include <stdio.h>
#include <stdlib.h>
typedef int status,Elemtype;
#define OK 1
#define NO 0
typedef struct Node
{
    status data;
    struct Node *next;
} Node;
typedef struct Node* Linklist;
void Initlist(Linklist *L)
{
    (*L)=(Linklist)malloc(sizeof(struct Node));
    (*L)->data=0;
    (*L)->next=NULL;
}
status Listinsert(Linklist *L,int j,Elemtype e)     ////正确
{
    Linklist p,r;
    p=*L;
    int i=2;
    r=(Linklist)malloc(sizeof(Node));
    r->data=e;
    r->next=NULL;
    while((*L)&&i<j)
    {
        i++;
        p=p->next;
    }
    r->next=p->next;
    p->next=r;
    return OK;
}


status Getelem(Linklist L,int j,Elemtype *e)
{
    Linklist p;
    int i;//
    for(i=0; i<j-1; i++)
    {
        p=L->next;
        L=p;

    }
    L->next=NULL;
    (*e)=L->data;
    return OK;
}


void showlist(Linklist L)
{
    Linklist p;
    while(L)
    {
        printf("%d\n",L->data);
        p=L->next;
        L=p;
    }
}



int main()
{
    int x=1;
    int *e=&x;
    Node *root,first,second,third;
    first.data=1;
    first.next=&second;
    second.data=2;
    second.next=&third;
    third.data=3;
    third.next=NULL;
    root=&first;
    //showlist(root);

   // if(Getelem(root,3,e))
     //   printf("%d",*e);
        if(Listinsert(&root,3,4)==1)
           showlist(root);




    return 0;
}

解决方案

您好,我觉得问题是这样的,在函数的这个形式

status Listinsert(Linklist *L,int j,Elemtype e)
{
    Linklist p,r;
    //p=(*L); //下面用(*L)替换p,运行后有问题
    int i=2;
    r=(Linklist)malloc(sizeof(Node));
    r->data=e;
    r->next=NULL;
    while(i<j)
    {
        i++;
        (*L)=(*L)->next; //替换
    }
    r->next=(*L)->next;  //替换
    (*L)->next=r;   
    return OK;
}

里有一个这样的问题,我不知道您是为了什么原因这样申明,在前面的这句话:typedef struct Node 星 Linklist;里,您已经把LinkList申明成了一个节点的指针类型,而显然您的这个函数传入的第一个参数是这个链表的头结点,但是您是这样写的Linklist 星L,这样相当于这样写了这句话:Node星 星L,相当于传入了一个指针的指针,而在一般的插入运算里都是直接传入LinkList L;这样就好了,因为可能您在别的地方看到过这种写法,即不在执行插入的子函数里再申明一个节点的指针,把头结点的值赋给这个临时的结点指针在操作,而是直接用头结点来操作,虽然这是可行,但是这无疑会产生误解,因为这个过程改变了这个头结点的值(即可能改变了这个头结点的指向),但是由于c语言的子函数参数调用是传值调用,即子函数在操作的不是这个原值而是操作他在这一次过程里创建的副本所以你在子函数里的操作对原值不会有什么改变,所以虽然在逻辑上这个过程是不那么完美的,但是他还是完成了功能,但是在c语言里当参数是指针的时候,虽然是传值调用,但是由于解指针应用,子函数通过指针副本可以直接操作指针指向的目标(除非在指针应用加上const限制),这也就是您的这个问题出现的原因,您创建的是一个节点指针的指针,当进行操作时,你通过头结点的指针的指针在这个步奏里改变了头结点的指向:

while(i<j)
    {
        i++;
        (*L)=(*L)->next; //因为L是头结点指针的指针,您这一步导致头结点变化!
    }

所以您可以更换插入的位置(这里假设我插入的值为5),比如您可以更换插入的位置,比如2,因为j=2,所以这个循环不进行,所以您可以看到显示为1,5,2,3当插入的位置为3时,j=3,这个循环执行一次这个显示为2,5,3,4就是头指针发生了一次偏移!您这样的写法导致了一边插入的同时,一边头结点在相应的后移!最后我觉得这个算法出现问题的原因是您使用了指针的指针。

这篇关于java - 链表插入函数问题,关于指针指向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆