C语言单链表的插入求解了

对于带有头结点的链表,为什么在插入方法需要传入头指针的地址(二重指针)?对于不带头结点的链表,插入或者删除第一个元素时,需要使用头指针的地址,可是对于带头结点链表,为何要呢?

4个回答

图片说明

chaobo_lu
零度永恒 回复一个蛋卷: 不是你表达不好,我已经图文并茂了,还是没让你看明白,是我的过。
接近 4 年之前 回复
chaobo_lu
零度永恒 回复一个蛋卷: 为什么要传入两重指针? 原因是这样的 你传入两重指针 你才能操作到你要传入的指针, 传入单冲指针的话就会出现我途中所说的你不期望的现象
接近 4 年之前 回复
u010707039
KingfarOu 非常感谢您的回答,图片文字看得出来您很认真,但我发现可能是我表达不好,几个回答都没搞清我的问题,我问的是为什么要传入头指针的地址(二重指针),所有评论区的回答都是为什么要传入头结点的地址(一重指针),我不晓得是不是我表达不好,不过还是非常感谢您的回答
接近 4 年之前 回复

传入头节点的地址后,你在函数中改变链表在调用的地方也可以生效,但是如果直接传头节点,那么你就要在函数中return头节点,然后在调用处接收

q3733353520
我用双手-成就你的梦想 回复linux_liyi: 头节点本身就是个指针,它的指针就是二重指针
接近 4 年之前 回复
q3733353520
我用双手-成就你的梦想 回复一个蛋卷: 头节点本身就是这个指针,它的指针就是二重指针
接近 4 年之前 回复
u010707039
KingfarOu 对啊应该要传入头结点地址,不过头结点的地址不是一重指针就够了么,我是认可需要传入头结点地址啊,可是头结点的地址不是一重指针就够了么
接近 4 年之前 回复

C语言不像C++,没有引用参数,所以参数的形参被改变不能作用到实参上。
比如
void foo(int i)
{
i = 2;
}

int i = 1;
foo(i); // i还是1

为此,需要指针:

void foo(int* i)
{
*i = 2;
}

int i = 1;
foo(&i); // 这样i=2了

这里需要初始化一个指针,指针本身相当于那个i,改变指针的指针指向的对象,才能给一个新的指针。

u010707039
KingfarOu 非常感谢您的回答,您说这个我知道的,提问之前我就知道,我是想说您没明白我的问题,也有可能是我表达得不够好,我是觉得带头结点链表,在插入和删除元素那时,只要传入头结点的地址就行(一重指针),不用传入头指针的地址(二重指针)
接近 4 年之前 回复

这里配有测试代码,
插入删除操作仅仅传入头结点的地址(一重指针),
没有传入头指针的地址(二重指针),
这个程序测试过后没有问题,还请大家能够指导

#include
#include
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
//定义节点的结构体
struct Node{
ElemType data;
struct Node* next;
};
typedef struct Node Node;

Status ListInit(Node** L,int n);//单链表初始化函数
Status GetElem(Node* L,int i,ElemType e);//获取单链表指定位置的元素
Status ListInsert(Node
L,int i,ElemType e);
Status ListDelete(Node* L,int i,ElemType e);
void printList(Node
L);

int main(){
Node* L;
int q = 0;
ListInit(&L,2);//初始化出一个联邦
ListInsert(L,3,3);//链表三号位置插入一个元素
ListInsert(L,4,4);//链表四号位置插入一个元素
if(ListDelete(L,3,&q)==OK)//删除三号位置上的元素
printf("q==%d\n",q);
printf("打印单链表的所有数据\n");
printList(L);
return 0;
}

//单链表初始化函数
//创建带有N个结点的单链表
//所有数据域初始化为零
Status ListInit(Node** L,int n){
Node* head = (Node*)malloc(sizeof(Node));//申请内存来创建头结点
Node* p = NULL;
if(head==NULL)
return ERROR;
head->data = 0;
head->next = NULL;
L = head;
//用头插法来创建各节点
for(int i = 0;i<n;i++){
p = (Node
)malloc(sizeof(Node));
p->data = 0;
p->next = (*L)->next;
(*L)->next = p;
}
return OK;
}
//传入带有头结点单链表的头指针(就是传入头结点的地址)
Status GetElem(Node* L,int i,ElemType e){
int j = 1;
Node
p = L->next;//让p指向链表的第一个元素
while(p!=NULL && j p = p->next;
j++;
}
//如果传入i的位置不对返回错误
//p==NULL说明所选择的位置超出链表的长度了
//j>i说明i==0
if(p==NULL||j>i)
return ERROR;
*e = p->data;
return OK;
}

//在单链表第i个元素的前面插入元素
//传入的是单链表的头指针的地址来的
//部分书籍这个函数的定义是
//Status ListInsert(Node** L,int i,ElemType e)
Status ListInsert(Node* L,int i,ElemType e){
Node* p = NULL;
int j;
p = L;//p指向连表的头结点了
j = 0;
while(p!=NULL && j p = p->next;
j++;
}
//p==NULL说明所选择的位置超出链表的长度了
//j>i-1表示i if(p==NULL || j>i-1){
return ERROR;
}
//如果能走到这一步
//说明p已经指向了第i-1个元素了
Node * s = (Node*)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}

/*
删除单链表第i个位置上的元素
有些数据这个函数的定义是
Status ListDelete(Node** L,int i,ElemType e)
/
Status ListDelete(Node
L,int i,ElemType e){
Node
p = L;//让P指向单链表头结点
Node* q = NULL;
int j = 0;
while(p->next!=NULL && j p = p->next;
j++;
}
if(p->next==NULL || j>i-1)
return ERROR;
//走到这里说明P指向了第i-1个元素了
*e = p->next->data;
q = p->next;
p->next = p->next->next;
free(q);
return OK;
}

/*
打印链表里的所有元素
/
void printList(Node
L){
L = L->next;//让L指向链表的第一个元素
while(L!=NULL){
printf("%d ",L->data);
L = L->next;
}
printf("\n");
}

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!