算法本身非常简单,就是最普通的单链表,插入。
不解的地方在于,为什么第一个形参要用按引用传参?
下面算法是摘自严蔚敏老师的数据结构。
问题具体描述:
为什么 Status ListInsert_L(LinkList &L, int i, ElemType e) 这里用"引用的L",这里L的形参明显可以用按值传递啊?
以下是结构体定义和插入算法:
typedef struct LNode{
ElemType data;
struct LNode * next;
}LNode, *LinkList;
Status ListInsert_L(LinkList &L, int i, ElemType e) { // 算法2.9 // 在带头结点的单链线性表L的第i个元素之前插入元素e
LinkList p,s;
p = L; //_________________________________________________________注意这里是整个算法唯一的L用到的地方就赋了个值!!!干什么用引用?)
int j = 0;
while (p && j < i-1) { // 寻找第i-1个结点
p = p->next;
++j; }
if (!p || j > i-1) return ERROR; // i小于1或者大于表长
s = (LinkList)malloc(sizeof(LNode)); // 生成新结点
s->data = e; s->next = p->next; // 插入L中
p->next = s; return OK;
} // LinstInsert_L
如果参数L按值传递,那就不能返回Status了,另外链表插入当然是用引用了,目的是要改变链表而不是生成一个新链表返回。
如果参数L按值传递,那就不能返回Status了,???什么理由
另外链表插入当然是用引用了,目的是要改变链表而不是生成一个新链表返回。 ???
L在函数外就存在,我用L找到链表,然后修改结点,L自然就会指向新的链表。为什么要用引用?
这儿用了指针的引用,因为你如果只是单单传入链表的头指针,在这个函数里添加节点成功了,但是函数参数传递仍然是值传递,当你退出这个函数时,你添加的节 点的“头指针”就找不到了,因为他是形参。所以,如果要在函数里改变实参,只能用再次用指针了,也就是二阶指针,不过在这儿用了指针的引用,效果和二阶指 针一样 的
添加的节 点的“头指针”就找不到了???
单链表插入函数 就用到了函数外已经存在的 头指针L ,通过L找到链表,然后找到结点i,在前面插入新结点,并将新节点的指针s保存在p指针指向的结点的指针域(p->next = s;)我搞不明白,哪里关形参是按值传递,还是按引用传递了。这里所有的操作都是基于指针的,必须都可以保存的。
我也觉得完全不需要传LinkList的引用,LinkList本来就是一指针,再传引用,这不是画蛇添足么...
我觉得2楼的意思可能是想说,L在调用前指向的是待插入链表的首节点,调用后指向的是新插入的节点,但是就上面这些代码来看,根本做不到这一点,要是最后加一句L = s才对嘛
算法第二句p=L,就是把L指向的头结点,让指针p也指向。
而且p和L都是指向的头结点,不是第一个数据结点,不可能“调用后指向的是新插入的节点”
新插入的结点必须在头结点之后的,头结点的指针域指向第一个数据结点。
@宇宙联盟委员: 如果L是传进去的引用,在函数返回前加上句L = s,那返回后的L是不是指向了新插入的节点?
你已经有自己的想法了,接下来只要验证下该想法是否正确就可以了。他用了引用传递,你改为普通的值传递,如果能达到一样的效果,就证明你的想法没错了,大胆怀疑+测试=真理,书上不一定都是对的,有的人为了图方便,不管内部实现如何,外部都用引用传递以达到不变应万变。
讲的好,我也是这么想的。主要是这个问题我还问了算法老师,她说可能严蔚敏老师还有什么意思在里面,我得下下周五,老师给我答案,中间她出差了。。。
因为头指针可能会被改掉(在新元素会成为头的情况下)
这是带头结点的链表,所以头一直是头结点。不会出现那种情况