链表中插入与删除节点
按顺序插入节点
《链表一》中已经介绍了两种添加节点的方法:添加到最前面、或者添加到末尾。
这里再介绍一种按排序插入的情况。例如,要求链表中的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;
}