文章目录
一. 链表的定义
① 基本概念
② 单链表
③ 概念解释
-
表头节点
-
数据节点
-
尾节点
④ 优缺点
优点
缺点
注意:
单向链表创建头文件 LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 要注意,链表本身有结构体,然后链表的节点也是一个结构体
// 链表节点
typedef struct LINKNODE
{
void *data; // 指向任何数据类型
struct LINKNODE *next; // 指向下一个节点
} LinkNode;
// 链表结构体
typedef struct LINKLIST
{
LinkNode *head;
int size; // 链表的大小
} LinkList;
// 打印函数指针
typedef void(*PRINT_PTR)(void *);
// 初始化链表
LinkList *init_linkList();
// 指定位置插入
void insert_linkList(LinkList *list, int pos, void *data);
// 删除指定位置的值
void remove_by_pos_linkList(LinkList *list, int pos);
// 获取链表的长度
int get_size_linkList(LinkList *list);
// 查找,根据数据进行查找
int find_linkList(LinkList *list, void *data);
// 返回第一个节点
void *front_linkList(LinkList *list);
// 打印链表节点
void print_linkList(LinkList *list,PRINT_PTR print);
// 释放链表内存
void free_space_linkList(LinkList *list);
#endif // !LINKLIST_H
实现
#include "LinkList.h"
// 初始化链表
LinkList *init_linkList()
{
LinkList *list = (LinkList *)malloc(sizeof(LinkList));
if (list != NULL)
{
list->size = 0;
// 初始化头结点,头结点是不保存数据信息的
list->head = (LinkNode *)malloc(sizeof(LinkNode));
if (list->head != NULL)
{
list->head->data = NULL;
list->head->next = NULL;
return list;
}
}
return NULL;
}
// 指定位置插入
void insert_linkList(LinkList *list, int pos, void *data)
{
// 插入元素,指定位置插入,链表的位置序号,从头结点开始,索引是0,后面累加
if (list == NULL || data == NULL)
{
return;
}
// 下标越界的友好处理,如果下标越界,就放到链表的尾部
if (pos < 0 || pos > list->size)
{
pos = list->size;
}
// 创建新的节点
LinkNode *newNode = (LinkNode *)malloc(sizeof(LinkNode));
if (newNode == NULL)
{
return;
}
newNode->data = data;
newNode->next = NULL;
// 找节点 辅助指针变量
LinkNode *pCurrent = list->head;
// 一开始指向头结点,则遍历到pos-1次以后,指向的位置就是pos的前一个节点
for (int i = 0; i < pos; i++)
{
pCurrent = pCurrent->next; // 寻找下一个节点
}
// 循环结束之后pCurrent指向的节点位置是pos-1位置,现在是pos位置插入新的节点.
// 相当于是在pos位置插入一个节点
// 先将新节点,指向原来的pos位置
newNode->next = pCurrent->next;
// 然后是pos位置的前一个位置,指向新节点
pCurrent->next = newNode;
// 链表的长度加1
list->size++;
}
// 删除指定位置的值
void remove_by_pos_linkList(LinkList *list, int pos)
{
if (list == NULL)
{
return;
}
if (list != NULL)
{
if (pos < 0 || pos >= list->size)
{
return;
}
// 查找删除节点的前一个节点,注意head不是数据节点,所以遍历多少次,指向的就是那个位置的节点
LinkNode *pCurrent = list->head;
for (int i = 0; i < pos; i++)
{
pCurrent = pCurrent->next;
}
// 缓存删除的节点
LinkNode *pDel = pCurrent->next;
pCurrent->next = pDel->next;
// 释放删除节点的内存
free(pDel);
list->size--;
}
return;
}
// 获取链表的长度
int get_size_linkList(LinkList *list)
{
if (list != NULL)
{
return list->size;
}
return -1;
}
// 查找,根据数据的值进行查找,返回节点的位置
int find_linkList(LinkList *list, void *data)
{
if (list != NULL && data != NULL)
{
LinkNode *pCurrent = list->head->next;
int i = 0;
while (pCurrent != NULL)
{
if (pCurrent->data == data)
{
break;
}
pCurrent = pCurrent->next;// 节点移动
i++;
}
return i;
}
}
// 返回第一个节点的数据
void *front_linkList(LinkList *list)
{
if (list != NULL)
{
return list->head->next->data;
}
return NULL;
}
// 打印链表节点
void print_linkList(LinkList *list, PRINT_PTR print)
{
if (list == NULL)
{
return;
}
// 辅助指针变量
LinkNode *pCurrent = list->head->next;
while (pCurrent != NULL)
{
print(pCurrent->data);
pCurrent = pCurrent->next;
}
}
// 释放链表内存
void free_space_linkList(LinkList *list)
{
if (list != NULL)
{
LinkNode *pCurrent = list->head;
while (pCurrent != NULL)
{
// 缓存下一个节点
LinkNode *pNext = pCurrent->next;
free(pCurrent);
pCurrent = pNext;
}
// 释放链表内存
free(list);
}
return;
}
测试
#include "LinkList.h"
typedef struct PERSON
{
char name[64];
int age;
int score;
} Person;
// 打印函数
void my_print(void *data)
{
Person *p = (Person *)data;
printf("Name:%s Age:%d Score:%d \n", p->name, p->age, p->score);
}
int main()
{
// 创建链表
LinkList *list = init_linkList();
// 创建数据
Person p1 = { "aaaa",29,100 };
Person p2 = { "bbbb",28,90 };
Person p3 = { "cccc",27,80 };
Person p4 = { "dddd",26,70 };
Person p5 = { "eeee",25,60 };
Person p6 = { "ffff",24,50 };
// 数据插入链表,头部插入
insert_linkList(list, 0, &p1);
insert_linkList(list, 0, &p2);
insert_linkList(list, 0, &p3);
insert_linkList(list, 0, &p4);
insert_linkList(list, 0, &p5);
insert_linkList(list, 0, &p6);
print_linkList(list, my_print);
// 删除3
remove_by_pos_linkList(list, 3);
printf("**********************************\n");
print_linkList(list, my_print);
// 返回第一个节点
printf("查找结果-------------------------------------\n");
Person *ret = (Person *)front_linkList(list);
printf("Name:%s,Age:%d,Score:%d\n", ret->name, ret->age, ret->score);
// 销毁链表
free_space_linkList(list);
return 0;
}