线性表可以分成两种 一种就是顺序表 也就是我们所熟知的数组 一种是今天的主角–链表
他们两者的区别在于 前者是顺序储存元素的 即数组元素的地址值是连续的
后者则是链式储存的 节点的地址值不一定连续
链表中的节点是由两部分组成的 一部分是数据域 另外一部分是指针域
而且一般都是由虚拟头节点开头的 虚拟头节点的数据域储存的是链表的长度 指针域指向的是实际的头节点
#include <stdio.h>
#include <stdlib.h>
// 定义一个节点的结构体
typedef struct Node{
int data;// 数据域
struct Node* next;// 指针域 由于这边还未起好别名 所以不能直接使用Node*
}Node;
// 定义一个函数 用于初始化链表
Ndoe* initList(){
// 无非就是创建一个虚拟头节点
Node* list = (Node*)malloc(sizeof(Node));
list->data = 0;
list->next = NULL;
return list;
}
// 定义一个函数 用于进行头插操作
void headInsert(Node* list, int data){
// 一定要注意两个节点的指针域修改顺序 先改待插入节点的next 然后在修改虚拟头节点的next
Node* newHead = (Node*)malloc(sizeof(Node));
newHead->data = data;
newHead->next = list->next;
list->next = newHead;
// 最后别忘了更新链表的长度
list->data++;
}
// 定义一个函数 用于进行尾插操作
void tailInsert(Node* list, int data){
// 你不要遍历过头了 如果当前节点的下一个节点为空的话 就停止遍历操作 而不是当前节点为空才停止遍历 因为你的目的是取出尾节点 而不是NULL
// 保留你的虚拟头节点 因为list会随着遍历操作的进行而改变
Node* cur = list;
while(cur->next){
cur = cur->next;
}
Node* tail = (Node*)malloc(sizeof(Node));
tail->data = data;
tail->next = NULL;
cur->next = tail;
list->data++;
}
// 定义一个函数 用于删除指定元素对应的节点(删除第一个符合条件的节点就行了) 还得通过返回值表示删除成功与否
int delete(Node* list, int data){
Node* pre = list->next;
Node* cur = list->next;
while(cur){
// 这边的循环条件有别于tailInsert的原因在于 这边需要判断所有的节点是否和指定值相同 而tailInsert目的则是获取一个链表的尾节点而已
if(cur->data == data){
pre->next = cur->next;
free(cur);
// 更新链表长度
list->data--;
// 我们用1表示删除成功
return 1;
}
// 如果当前节点不符合条件的话 则继续往下进行寻找
pre = cur;
cur = cur->next;
}
// 如果循环结束以后 都没有找到指定节点的话 说明删除失败
return 0;// 我们用0表示删除失败
}
void printList(Node* list){
Node* cur = list->next;
while(cur){
printf("%d ", cur->data);
cur = cur->next;
}
}
测试代码如下所示:
int main() {
Node* list = initList();
headInsert(list, 1);
headInsert(list, 2);
headInsert(list, 3);
headInsert(list, 4);
tailInsert(list, 5);
printList(list);
if (delete(list, 0)) {
printf("删除成功\n");
}
else {
printf("删除失败\n");
}
printList(list);
return 0;
}
如果单向链表的删除操作中 需要将指定值对应的所有节点都进行删除的话 那么需要用一下代码进行代替
int delete(Node* list, int data){
// 定义一个变量 用于储存所删除元素的个数
int deleted = 0;
Node* pre = list->next;
Node* cur = list->next;
while(cur){
if(cur->data == data){
pre->next = cur->next;
free(cur);
list->data--;
// 同时需要更新deleted变量 因为后面需要通过该变量进行删除成功与否的判断
deleted++;
// 但是现在pre所表示的节点不会变 但是cur表示的节点需要改变 cur需要更新为pre的下一个节点
cur = pre->next;
}else{
// 如果没有找到指定值对应的节点的话 那么就更新pre为cur 然后更新cur为当前节点的下一个节点
pre = cur;
cur = cur->next;
}
}
// 然后最后直接返回deleted 如果为0 说明删除失败 如果为1的话 那么说明删除成功 并且可以从中知道被删除元素的个数
return deleted;
}
测试代码如下所示:
int main() {
Node* list = initList();
headInsert(list, 1);
headInsert(list, 1);
headInsert(list, 2);
headInsert(list, 3);
headInsert(list, 4);
tailInsert(list, 5);
printList(list);
int deleted = delete(list, 1);
if (deleted) {
printf("删除成功 并且被删除的元素个数为%d\n", deleted);
}
else {
printf("删除失败\n");
}
printList(list);
return 0;
}