为什么在链表的删除或者插入的操作中要用二级指针?

同上

你好,其实这个问题我当时也迷糊了,后来想想其实也不难,呵呵,我们分析一下:
如果用C语言描述单链表如下:
typedef struct node{
DataType data;//节点的数据域
struct node *next;//节点的指针域
}ListNode;
typedef ListNode *LinkList;
ListNode *p;//p是节点
LinkList head;//head是头指针
注意最后一句:"LinkList head",这是定义了一个头结点,前面已经用typedef定义了LinkList,既“typedef ListNode *LinkList;”这句,这就说明LinkList head 定义后 head实际上是一个LinkNode类型的指针,这是我们单单看最后两句的定义而忽略其字面意思而言的话,p和head实际上是同一种类型的变量,都是ListNode类型的指针,只不过最后一句LinkList类型是用typedef定义的,所以没有“*”号。
因为删除或者插入操作有时会修改实参的指针(比如头结点为空的时候插入节点,这是就修改了头结点),那么就必须将相应的形参说明为指针的指针,函数电泳时将实参指针的地址传递给相应的形参。例如:刚刚初始化的时候头结点head为空,如果这时插入节点p(由上可知p是ListNode*类型的,是个指针,把它当做地址)时应该是head=p;这就改变了head的地址,所以在传参数的时候,函数的形参一般都是"Insert(LinkList *head,DataType x)",
注意:head是ListNode*类型的,所以*head 是ListNode**类型的,不知道我说的楼主认为可以吗?
温馨提示:答案为网友推荐,仅供参考
第1个回答  2017-08-01
对于链表函数调用,在参数传递过程中使用二级指针的目的是因为需要对链表头指针有更改,比如要创建链表,那么新的节点都要在头节点之后,或者删除头节点之后的节点时需要。
函数调用可以看做是在这个函数中新建了一个同类型的变量,变量的值与实参的值一样。
typedef struct Node {
int data;
struct Node *next;
} LinkList;
对于这样一个结构体和如下的函数
void change(LinkList *l) {
LinkList *p;
p = l->next;
p->data = 10;
}
相当于在被调函数中新建了一个LinkList *(指针类型)的变量,它的值是主调函数传入的值,所以它也就指向我们主函数中创建的链表的头节点。这里对它的data值改变在主函数中也会生效。
但是如果要对头节点有改变,比如
void change2(LinkList *l) {
LinkList *s = (LinkList *)malloc(sizeof(LinkList));
l->next = s;
}
这样s只是添加到了被调函数中创建的链表指针的后面,而不是添加到主调函数链表头指针的后面,所以此函数执行完后对主调函数没有影响。所以这里应该传入二级指针
void change2(LinkList **l) {
LinkList *s = (LinkList *)malloc(sizeof(LinkList));
(*l)->next = s;
}
第2个回答  2011-08-29
这个是计算机考试公共基础的内容吧!在线性单链表中,每一个节点只有一个指针域,由这个指针只能找到后件结点,但不能找到前件结点。因此在单链表中只能顺指针向链尾方向进行扫描,这对于某些问题的处理会带来不便,因为在这种方式下,由某一个节点出发。只能找到他的后件,而为了找到他的前件必须从头开始找!未了弥补单链表这个缺点,我们采用双向链表,它的每个节点设有两个指针,左指针和右指针,左指针指向前件,右指针指向后件。循环链表相比前面的单链表有两个特点:增加了一个表头指针:链表最后一个节点的指针域不是空,而是指向表头结点,这就形成循环了!再循环链表中,只要指出表中任意一个结点的位置,就可以从它出发访问表中其他所有的结点,耳线性链表做不到这一点。
以上介绍了他们的特点,插入和删除运算就是利用栈来进行,而首先就是查找指定元素,以上三个查找上的不同决定了插入和删除的效率。此外循环链表和单链表的插入删除基本一样,都是一个指针,就是查找指定元素时方式不一!!!

希望可以帮到你!!!
追问

单链表中,有一个专门删除节点的函数,这个函数的实参是 NODE **head;就是二级指针,为什么?
不好意思,你上面的回答,我还是不懂!!!

相似回答