Bootstrap

【数据结构】【线性表】单链表2—单链表的插入(附C语言源码)

单链表的插入

单链表的插入可以分为按位序插入指定结点的前插和后插
按位序插入
按位序插入,则在链表的第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;			//插入成功
}

;