视频【C语言数据结构 培养架构师思维】 P9-P10内容
https://www.bilibili.com/video/BV1Pb411g7bU/?share_source=copy_web&vd_source=1f125f59acec416a3d726792acdc05fd
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//链表结点
struct LinkNode
{
void* data; //数据域
struct LinkNode* next; //指针域
};
//链表结构体
struct LList
{
struct LinkNode pHeader; //头结点
int m_Size; //链表长度
};
typedef void* LinkList;
//初始化链表
LinkList Init_LinkList()
{
struct LList* myList = malloc(sizeof(struct LList));
if(myList == NULL)
{
return NULL;
}
//初始化链表结构体
myList->pHeader.data = NULL;
myList->pHeader.next = NULL;
myList->m_Size = 0;
return myList;
}
//插入结点
void Insert_LinkList(LinkList List, int pos, void* data)
{
if(List == NULL)
{
return;
}
if(data == NULL)
{
return;
}
struct LList* myList = List;
//无效位置进行尾插
if(pos<0 || pos>myList->m_Size)
{
pos = myList->m_Size;
}
//创建临时结点
struct LinkNode* pCurrent = &myList->pHeader;
//找到插入位置的前驱结点
for(int i = 0; i<pos; i++)
{
pCurrent = pCurrent->next;
}
//创建新结点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->data = data;
newNode->next = NULL;
//将新结点插入链表
newNode->next = pCurrent->next;
pCurrent->next = newNode;
//链表大小+1
myList->m_Size++;
}
//遍历链表
void Foreach_LinkList(LinkList List, void(*MyPrintf)(void*))
{
if(List == NULL)
{
return;
}
struct LList* myList = List;
//找到第一个有数据的节点
struct LinkNode* pCurrent = myList->pHeader.next;
for(int i = 0; i<myList->m_Size; i++)
{
MyPrintf(pCurrent->data);
pCurrent = pCurrent->next;
}
}
//按位置删除结点
void RemoveByPos_LinkList(LinkList List, int pos)
{
if(List == NULL)
{
return;
}
struct LList* myList = List;
//无效位置删除
if(pos<0 || pos>myList->m_Size-1)
{
return;
}
//找到删除结点的前驱结点
struct LinkNode* pCurrent = &myList->pHeader;
for(int i = 0; i<pos; i++)
{
pCurrent = pCurrent->next;
}
//待删除的结点
struct LinkNode* pDel = pCurrent->next;
//更改指针指向,修改待删除结点的前驱结点指向,指向待删除结点的后驱结点
pCurrent->next = pDel->next;
//释放掉待删除的结点
free(pDel);
pDel = NULL;
//更新链表长度
myList->m_Size--;
}
//按值删除结点
void RemoveByValue_LinkList(LinkList List, void* data, int(*mycompare)(void* data1, void* data2))
{
if(List == NULL)
{
return;
}
if(data == NULL)
{
return;
}
struct LList* myList = List;
//创建两个辅助指针变量,第一个指向当前结点的前驱结点,第二个指向当前节点
struct LinkNode* pPrev = &myList->pHeader;
struct LinkNode* pCurrent = pPrev->next;
for(int i = 0; i < myList->m_Size; i++)
{
if(mycompare(pCurrent->data, data))
{
//更改指针指向
pPrev->next = pCurrent->next;
//释放掉要删除的结点
free(pCurrent);
pCurrent = NULL;
myList->m_Size--;
break;
}
//每循环一次,数据比对不一致时,结点都往后移动一个
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
return;
}
//清空链表
void Clean_LinkList(LinkList List)
{
if(List == NULL)
{
return;
}
struct LList* myList = List;
struct LinkNode* pCurrent = myList->pHeader.next;//第一个有数据的结点
for(int i = 0; i < myList->m_Size; i++)
{
struct LinkNode* pNext = pCurrent->next;//要删除结点的下一个结点
free(pCurrent);
pCurrent = pNext;
}
myList->pHeader.next = NULL;
myList->m_Size = 0;
return;
}
struct Person
{
char name[64];
int age;
};
//输出函数,用于遍历
void MyPrintf(void* data)
{
struct Person* p = data;
printf("姓名:%s 年龄:%d \n", p->name, p->age);
}
//比较函数,用于对比数值,一致返回1,不一致返回0
int MyComparePerson(void*data1, void* data2)
{
struct Person* p1 = data1;
struct Person* p2 = data2;
return (strcmp(p1->name, p2->name) == 0) && (p1->age == p2->age);
}
int main()
{
//初始化链表
LinkList myList = Init_LinkList();
//插入数据
struct Person p1= {"小一", 11};
struct Person p2= {"小二", 12};
struct Person p3= {"小三", 13};
struct Person p4 = {"小四", 14};
struct Person p5 = {"小五",15};
struct Person p6 = {"小六", 16};
struct Person p7 = {"小三", 13};
struct Person p8 = {"小八", 18};
printf("//\n");
//插入
Insert_LinkList(myList, 0, &p1 );
Insert_LinkList(myList, 0, &p2 );
Insert_LinkList(myList, 2, &p3 );
Insert_LinkList(myList, 10, &p4 );
Insert_LinkList(myList, 1, &p5 );
Insert_LinkList(myList, 4, &p6 );
//遍历输出链表
printf("插入后的链表:\n");
Foreach_LinkList(myList, *MyPrintf);//理想顺序:小二 小五 小一 小三 小六 小四
printf("//\n");
//通过位置删除,并遍历
RemoveByPos_LinkList(myList, 2);
printf("按位置删除后的链表:\n");
Foreach_LinkList(myList, *MyPrintf);//理想顺序:小二 小五 小三 小六 小四
printf("//\n");
//通过值来删除,并遍历
RemoveByValue_LinkList(myList, &p7, *MyComparePerson);
printf("按值删除后的链表:\n");
Foreach_LinkList(myList, *MyPrintf);//理想顺序:小二 小五 小六 小四
printf("//\n");
//通过值来删除,并遍历
RemoveByValue_LinkList(myList, &p8, *MyComparePerson);
printf("按值删除后的链表:\n");
Foreach_LinkList(myList, *MyPrintf);//理想顺序:小二 小五 小六 小四
//销毁动态数组
Clean_LinkList(myList);
return 0;
}