链表 三

链表中插入与删除节点
按顺序插入节点
《链表一》中已经介绍了两种添加节点的方法:添加到最前面、或者添加到末尾。
这里再介绍一种按排序插入的情况。例如,要求链表中的Student对象的id按从小到大顺序。
原链表中已经存在1,3,4,8四个节点,新入一个ID为5的节点,如下图所示:

由于每个节点插入的时候,都是按顺序插入的,所以最终这个链表是按顺序排列的。
如何实现按顺序插入?
方法:在插入时,遍历链表,并比较ID的值,找到目标位置
链表插入的核心操作,是找到目标位置,并记录前一个节点pre。
新节点直接挂在pre后面就行了,这个操作很简单

obj->next = pre->next;
pre->next = obj;

例如

// 按顺序插入节点
int insert(Student* obj)
{	
Student* cur = &m_head.next; // 当前节点current	
Student* pre = &m_head;  // 上一个节点previous	
while(cur)	
{				
if(obj->id < cur->id) // 找到这个位置			
break;		
pre = cur;		
cur = cur->next;  // 找到最后一个对象	
} 	
// 插入到pre节点的后面	
obj->next = pre->next;	
pre->next = obj;	
return 0;
}

查找和删除节点
删除节点的核心目标:找到这个节点,并记录该节点的前一个节点pre。
删除:

pre->next = obj->next;
free(obj);

例如

// 按id查找并删除节点
void remove(int id)
{	
Student* cur = m_head.next; // 当前节点current	
Student* pre = &m_head;  // 上一个节点previous	
while(cur)	
{				
if(id == cur->id) // 找到这个位置		
{			
// 删除该节点			
pre->next = cur->next;			
free(cur);			
break;		
}		
pre = cur;		
cur = cur->next;  // 找到最后一个对象	
}
}

与数组比较
数组:如果要在中间插入/删除一个对象,那么要把后面所有的元素后移,花费的cpu时间较多
链表:在中间插入/删除一个对象,不需要数据移动,直接挂中“链条”中即可
所以,链表比数组适合插入/删除操作,性能较高
与“无头链表”比较
为什么不使用“无头链表”?
因为“无头链表”的插入和删除都比较复杂。当要操作的节点位于头部时,非常复杂。
“有头节点”只是增加了一个固定的头部,在内存空间上的浪费是可以忽略不计的。但是带来的方便却是非常地大。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 struct Student
 {	
 int id;	
 char name[16];	
 Student* next;
 }; 
 // 定义了一个有头节点
 Student m_head = {0}; 
 // 按顺序插入节点
 int insert(Student* obj)
 {	
 Student* cur = m_head.next; // 当前节点current	
 Student* pre = &m_head;  // 上一个节点previous	
 while(cur)	
 {				
 if(obj->id < cur->id) // 找到这个位置			
 break; 		
 pre = cur;		
 cur = cur->next;  // 找到最后一个对象	
 } 	
 // 插入到pre节点的后面	
 obj->next = pre->next;	
 pre->next = obj;	
 return 0;
 } 
 // 按id查找并删除节点
 void remove(int id)
 {	
 Student* cur = m_head.next; // 当前节点current	
 Student* pre = &m_head;  // 上一个节点previous	
 while(cur)	
 {				
 if(id == cur->id) // 找到这个位置		
 {			
 // 删除该节点			
 pre->next = cur->next;			
 free(cur);			
 break;		
 }		
 pre = cur;		
 cur = cur->next;  // 找到最后一个对象	
 }
 } 
 // 遍历
 void show_all()
 {	
 Student* p = m_head.next; 	
 while(p)	
 {		
 printf("ID: %d, name: %s\n", p->id, p->name);		
 p = p->next; // 下一个对象	
 }
 }
 int main()
 {	
 Student* obj = NULL;	 	
 obj = (Student*)malloc (sizeof(Student));	
 obj->id = 8;	
 strcpy(obj->name, "888");	
 insert(obj); 	
 obj = (Student*)malloc (sizeof(Student));
 obj->id = 1;	
 strcpy(obj->name, "111");	
 insert(obj); 	
 obj = (Student*)malloc (sizeof(Student));	
 obj->id = 4;	
 strcpy(obj->name, "444");	
 insert(obj); 	
 obj = (Student*)malloc (sizeof(Student));
 obj->id = 3;	
 strcpy(obj->name, "333");	
 insert(obj); 	
 obj = (Student*)malloc (sizeof(Student));
 obj->id = 5;	s
 trcpy(obj->name, "555");	
 insert(obj); 	
 remove(3);
 remove(2);	
 show_all();	
 return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值