链表结构体
typedef struct LinkNode
{
int elem;
struct LinkNode *next;
}LinkNode, * ListLink;
typedef struct 后必须加链表名称,否则会出现“LinkNode * 值不能用于初始化LinkNode *”类型的错误
链表初始化
void Init(LinkList& L)
{
L = new ListNode;
L->next = NULL;
}
Init函数定义时,形参为LinkList& L。&L在C++中表引用,在C中为取地址。此处在定义函数的时候将函数的形参指定为引用,则在调用该函数时会将实参直接传递给形参,而不是将实参的拷贝传递给形参,故可直接对L分配内存空间。若形参为LinkList L,则是对其拷贝分配空间,对L实际上无影响。
链表结点的插入
void Insert(LinkList& L, int pos, int e)
{
LinkList p = L;
LinkList c =new ListNode;
while (pos)
{
p = p->next;
pos--;
}
//有头节点
if (p)
{
c->data = e;
c->next = p->next;
p->next = c;
}
}
插入时依旧采用引用传递的方式进行传参,这是因为插入结点实际上是对L的修改。在此定义了一个结点c,类型为LinkList。
if (p)
{
c.data = e;
c.next = p->next;
p->next = &c;
}
我一开始尝试使用ListNode来定义c,但在c.next = p.next时出现问题,显示如下图
经过逐步调试后,本文发现是由于c作为局部变量,在函数结束后被自动删除,导致L->next指向空,从而引发读取冲突。因此,c必须定义为LinkList类型,使用new分配空间。new动态分配的空间不会被自动删除,需采用delete手动删除,从而避免了该问题。
链表结点的删除
void Delete(LinkList& L, int pos)
{
LinkList p = L;
while (pos)
{
p = p->next;
pos--;
}
LinkList q = p->next;
p->next = p->next->next;
delete q;
}
由于采用首元结点,故对第一个结点的删除与其他别无二致。这里需要一个临时变量q指向p->next,从而在p->next指向后一个值时成功删除原先的p->next。