单向链表
** 注释非常丰富,并给出了测试例子,可直接编译运行!**
//
// Created by szw on 2021/9/17.
//
//
// Created by wen on 2021/9/15.
//
#define MISTAKE_1 1
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//定义节点结构
typedef struct LinkNode{
//数据域
void *data;
//指针域
struct LinkNode* next;
}LinkNode;
//定义链表结构
typedef struct LList{
//头节点
struct LinkNode pHeader;
//链表长度
int m_size;
}LList;
//保持数据操作安全性
typedef void * LinkList;
//初始化链表
LinkList init_LinkList(){
LList *myList = malloc(sizeof (LList));
//内存分配失败
if(myList==NULL)
{
return NULL;
}
//链表头结点数据初始化
myList->pHeader.data=NULL;
//链表头节点指针初始化
myList->pHeader.next=NULL;
myList->m_size =0;
//返回初始化链表
return myList;
}
//链表插入
void insert_LList(LList* list, int pos, void *data){
if(list==NULL)
{
return;
}
if(data==NULL)
{
return;
}
// 将地址还原成链表结构体
LList * myList = list;
//如果插入位置不准确
if(pos<0||pos >myList->m_size)
{
//无效的位置变成尾插
pos = myList->m_size;
}
//从头节点开始一步寻找到插入位置前的节点
LinkNode* pCurrent = &(myList->pHeader);
//开始寻找
for (int i = 0; i < pos; ++i) {
pCurrent = pCurrent->next;
}
//创立新节点
LinkNode * new_Linknode = malloc(sizeof (LinkNode));
//新节点赋值
new_Linknode->data =data;
new_Linknode->next =NULL;
//更新链表关系
new_Linknode->next=pCurrent->next;
pCurrent->next = new_Linknode;
//更新链表长度
myList->m_size ++;
}
//遍历链表
void foreach_Linklist(LinkList * list, void (*my_foreach_print)(void *)){
if(list == NULL){
return;
}
//链表结构体转换
LList *mylist = list;
//找一个临时节点指向链表的头节点的下一个节点的地址
LinkNode * tmp_node = mylist->pHeader.next;
for (int i = 0; i <mylist->m_size ; ++i) {
//不知道数据类型交给回调函数打印
my_foreach_print(tmp_node->data);
//找完数据继续往后移动
tmp_node = tmp_node->next;
}
}
//删除链表
//按着位置删除数据
void remove_Bypos_Linklist(LinkList* list, int pos){
if(list == NULL)
{
return;
}
//还原链表结构
LList *mylist = list;
//取链表的头指针
LinkNode *pCurrent = &(mylist->pHeader);
//判断无效位置
if(pos<0 ||pos >mylist->m_size-1)
{
return;
}
//进行循环查找出删除位置的前一个
for (int i = 0; i <pos ; ++i) {
pCurrent = pCurrent->next;
}
//记录待删除的节点
LinkNode * del_node = pCurrent->next;
//更改节点关系
pCurrent->next = del_node->next;
//释放节点
free(del_node);
del_node =NULL; //避免出现野指针
//更新链表长度
mylist->m_size -- ;
}
//按照值来进行删除数据
void remove_ByValue_Linklist(LinkList * list, void *data,int(*DataCompare)(void *,void *)){
//判断数据有效性
if(list == NULL)
{
return;
}
if(data == NULL)
{
return;
}
//还原链表
LList* myList = list;
//创建两个辅助指针
LinkNode * prev_node =&(myList->pHeader);//用来存储删除元素前一个元素
LinkNode *pCurrent_node = prev_node->next;//存储删除元素
//循环查找
for (int i = 0; i < myList->m_size; ++i) {
//将两个指针 pCurrent_node->data 与 data 比较交给回调函数
if(DataCompare(pCurrent_node->data,data))
{
//如果判断成立建立关系
prev_node->next = pCurrent_node->next;
//释放
free(pCurrent_node);
pCurrent_node = NULL;
//更新链表长度
myList->m_size --;
break;
}
//辅助指针后移
prev_node = pCurrent_node;
pCurrent_node = pCurrent_node->next;
}
}
//清空链表
void clear_LinkList(LinkList list){
if (list==NULL)
{
return;
}
//还原链表
LList *mylist = list;
//先找到有数据的那个结点
LinkNode * pCurrent = mylist->pHeader.next;
//一层层递进查找
for (int i = 0; i <mylist->m_size ; ++i) {
//创建指针,保存下一个位置
LinkNode * pNext = pCurrent->next;
free(pCurrent);
pCurrent = pNext;
}
//更新链表
mylist->pHeader.next = NULL;
mylist->m_size=0;
}
//返回链表长度
int size_LinkList(LinkList list){
if (list ==NULL)
{
return NULL;
}
//还原链表
LList * myList =list;
return myList->m_size;
}
//销毁链表
void destroy_LinkList(LinkList * list){
if (list== NULL)
{
return;
}
//首先清空
clear_LinkList(list);
// 删除掉
free(list);
list ==NULL;
printf("销毁链表成功\n");
}
typedef struct Person{
char name[64];
int age;
}Person;
//打印的回调函数
void Person_print(void *data){
Person *P =data;
printf("name:%s,age:%d\n",P->name,P->age);
}
//值比较的回调函数
int ComparePerson(void *data1,void *data2){
Person * P1 = data1;
Person *P2 =data2;
return strcmp(P1->name,P2->name)==0 && P2->age == P1->age;
}
//测试
void test01(){
//测试数据
Person P1 ={"tom1",1};
Person P2 ={"tom2",2};
Person P3 ={"tom3",3};
Person P4 ={"tom4",4};
Person P5 ={"tom5",5};
Person P6 ={"tom6",6};
Person P7 ={"tom7",7};
Person P8 ={"tom8",8};
Person P9 ={"tom9",9};
Person P10 ={"tom10",10};
Person a[10]={P1,P2,P3,P4,P5,P6,P7,P8,P9,P10};
//初始化链表
LinkList mylist = init_LinkList();
for (int i = 0; i <10; ++i) {
insert_LList(mylist,0,(a+i));
}
foreach_Linklist(mylist,Person_print);
//测试删除
// remove_Bypos_Linklist(mylist,3);
remove_ByValue_Linklist(mylist,&P1,ComparePerson);
printf("删除后\n");
foreach_Linklist(mylist,Person_print);
//测试返回链表长度
printf("链表长度:%d\n", size_LinkList(mylist));
//测试清空
clear_LinkList(mylist);
printf("链表长度:%d\n", size_LinkList(mylist));
//测试销毁
destroy_LinkList(mylist);
}
//清空链表
int main(){
test01();
return 0;
}