单链表的插入
单链表的插入可以分为按位序插入和指定结点的前插和后插
按位序插入
按位序插入,则在链表的第i位插入一个结点,由于链表是物理结构为链式存储的线性表,其存储内存不连续,依靠结点中元素数据中的指针数据指向下一结点,因此要插入一个结点到第i个位置,只需要找到第i-1个元素,将其指针数据给插入结点的指针数据,并将自己的指针数据更新为指向i即可。
/*功能:单链表在第i个位序插入一个结点
输入:
L->单链表结构体
i->插入到第i个位序
e->要插入的数据
输出:
flase:插入失败
true :插入成功
说明:该函数的插入方式适用于有头结点的单链表
*/
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1) //判断i是否有效
return false; //i无效,插入失败
LNode *p=NUll; //当前结点
int j=0; //当前结点是第几个位置
p=L; //初始化当前节点为头结点
while(p!=NULL && j<i-1){ //遍历找到第i-1个结点
p=p->next;
j++;
}
if(p==NULL) //i不合法
return flase; //i不合法,删除失败
LNode *s=(LNode *)malloc(sizeof(LNode));//申请插入结点空间
if(s==NULL) //判断空间申请状况
return false; //空间申请失败,插入失败
s->data=e; //将数据e给插入结点
s->next=p->next; //将i-1结点的next给插入结点
p->next=s; //i-1的next指针指向插入结点
return true; //插入成功
}
如果没有头结点,则无法找到第i-1个结点,因此要对i=1时进行特别处理
/*功能:单链表在第i个位序插入一个结点
输入:
L->单链表结构体
i->插入到第i个位序
e->要插入的数据
输出:
flase:插入失败
true :插入成功
说明:该函数的插入方式适用于没有头结点的单链表,对于i=1时需要特殊处理
*/
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1) //判断i是否在有效
return false; //i无效,插入失败
if(i==1){ //在第一个位置插入结点
LNode *s=(LNode *)malloc(sizeof(LNode));//申请插入结点空间
if(s==NULL) //判断空间申请状况
return false; //空间申请失败,插入失败
s->data=e; //将数据e给插入结点
s->next=L; //将L指向的结点指针给新结点
L=s; //L指向新结点
return true; //插入成功
}
LNode *p=NUll; //当前结点
int j=1; //当前结点是第几个位置
p=L; //初始化p指向第一个结点
while(p!=NULL && j<i-1){ //遍历找到第i-1个结点
p=p->next;
j++;
}
if(p==NULL) //i不合法
return flase; //i不合法,删除失败
LNode *s=(LNode *)malloc(sizeof(LNode));//申请插入结点空间
if(s==NULL) //判断空间申请状况
return false; //空间申请失败,插入失败
s->data=e; //将数据e给插入结点
s->next=p->next; //将i-1结点的next给插入结点
p->next=s; //i-1的next指针指向插入结点
return true; //插入成功
}
指定结点后插操作
将指定节点的原有的指针数据给插入结点,并更新现在的指针数据指向插入结点
/*功能:单链表在指定结点后插入一个结点
输入:
*p->指定的结点指针
e->要插入的数据
输出:
flase:插入失败
true :插入成功
说明:
*/
bool InsertNextNode(LNode *p,ElemType e){
if(p==NULL) //判断插入结点合法性
return false; //结点不合法,插入失败
LNode *s=(LNode *)malloc(sizeof(LNode));//申请插入结点空间
if(s==NULL) //判断空间申请状况
return false; //空间申请失败,插入失败
s->data=e; //将数据e给插入结点
s->next=p->next; //将i-1结点的next给插入结点
p->next=s; //i-1的next指针指向插入结点
return true; //插入成功
}
/*功能:单链表在指定结点后插入一个结点
输入:
*p->指定的结点指针
*s->要插入的结点
输出:
flase:插入失败
true :插入成功
说明:
*/
bool InsertNextNode(LNode *p,LNode *s){
if(p==NULL) //判断插入结点合法性
return false; //结点不合法,插入失败
s->next=p->next; //将i-1结点的next给插入结点
p->next=s; //i-1的next指针指向插入结点
return true; //插入成功
}
指定节点前插操作
在结点后插入很简单,只需要将该结点的next指针给新结点,同时更新该结点的next指针指向新结点。但要在指定结点前插入一个结点,需要找到该结点的前驱结点,又因为单链表不能逆向,因此需要遍历链表。我们也可以通过另一种方法,不找前驱结点,不改变前驱结点的next,而将新结点插入到指定结点的后面,再将指定结点与插入的新结点的所有数据交换,玩一手偷天换日。
/*功能:单链表在指定结点前插入一个结点
输入:
*p->指定的结点指针
e->要插入的数据
输出:
flase:插入失败
true :插入成功
说明:
*/
bool InsertPriorNode(LNode *p,ElemType e){
if(p==NULL) //判断插入结点合法性
return false; //结点不合法,插入失败
LNode *s=(LNode *)malloc(sizeof(LNode));//申请插入结点空间
if(s==NULL) //判断空间申请状况
return false; //空间申请失败,插入失败
s->data=p->data; //将p的数据给新结点
p->data=e; //将要被插入的数据给p
s->next=p->next; //将p的next给新结点
p->next=s; //将p的next指针指向新结点
/*此时新结点的所有内容与p结点完成互换,最终完成偷天换日*/
return true;//插入成功
}
/*功能:单链表在指定结点后插入一个结点
输入:
*p->指定的结点指针
*s->要插入的结点
输出:
flase:插入失败
true :插入成功
说明:
*/
bool InsertPriorNode(LNode *p,LNode *s){
if(p==NULL) //判断插入结点合法性
return false; //结点不合法,插入失败
ElemType temp=s->data; //创建临时变量temp暂存新结点的数据
s->data=p->data; //将指定结点数据给新结点
p->data=temp; //将新结点的数据换给指定结点
s->next=p->next; //将指定结点的next指针给新结点
p->next=s; //将指定节点的next指针指向新结点
return true; //插入成功
}