#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//节点的结构体
struct LinkNode {
//数据域
void* data;
//指针域(指向的仍然是节点)
struct LinkNode* next;
};
//整张链表的结构体
struct LinkList {
//头结点
struct LinkNode pHeader;
//链表的节点数量
int m_size;
};
typedef void* LList;
LList init_linkList() {
//给整张链表分配空间
struct LinkList* myList = malloc(sizeof(struct LinkList));
if (myList == NULL)
return NULL;
//初始化链表长度,以及链表头结点
myList->m_size = 0;
myList->pHeader.data = NULL;
myList->pHeader.next = NULL;
return myList;
}
//插入链表
void insert_linkList(LList linkList, int pos, void* data) {
if (linkList == NULL || data == NULL)
return;
struct LinkList* list = linkList;
if (pos < 0 || pos > list->m_size)
{
//对于无效的插入位置 ,直接强制做尾插
pos = list->m_size;
}
//让一个节点指针保存头结点的位置
struct LinkNode* pCurrentNode = &list->pHeader;
//让一个节点指向要插入位置的节点的前驱结点
for (int i = 0;i<pos;i++)
{
//nextNode++;链表不可以进行++操作,因为地址不连续
pCurrentNode = pCurrentNode->next;
}
//此时的pCurrentNode指向的是要插入位置的前驱
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->data = data;
//更新节点的连接关系
newNode->next = pCurrentNode->next;
pCurrentNode->next = newNode;
//更新链表长度
list->m_size++;
}
//遍历链表
void for_each_LinkList(LList linkList,void(*myPrint)(void *)) {
struct LinkList* list = linkList;
struct LinkNode * firstNode = list->pHeader.next;
for (int i = 0; i < list->m_size; i++)
{
myPrint(firstNode->data);
firstNode = firstNode->next;
}
}
//链表按位置删除
void delete_LinkList_pos(LList linkList,int pos) {
if (linkList == NULL)
return;
struct LinkList *list = linkList;
if (pos < 0 || pos >= list->m_size)
return;
struct LinkNode* pcurrentNode = &list->pHeader;
for (int i = 0; i < pos; i++)
{
pcurrentNode = pcurrentNode->next;
}
//循环结束pcurrentNode就指向要删除位置的前驱节点了
struct LinkNode* Del = pcurrentNode->next;
pcurrentNode->next = Del->next;
free(Del);
Del = NULL;
list->m_size--;
}
//链表按值删除
void delete_LinkList_value(LList linkList, void* data,int(*myCompare)(void*,void*)){
if (linkList == NULL || data == NULL)
return;
struct LinkList* list = linkList;
struct LinkNode* pPre = &list->pHeader;
struct LinkNode* pCurrent = pPre->next;
for (int i = 0; i < list->m_size;i++)
{
if (myCompare(pCurrent->data,data))
{
pPre->next = pCurrent->next;
free(pCurrent);
pCurrent= NULL;
list->m_size--;
break;
}
pPre = pCurrent;
pCurrent = pCurrent->next;
}
}
//提供返回链表长度的接口
int get_size_LinkList(LList linklist) {
if (linklist == NULL)
return -1;
struct LinkList* list = linklist;
return list->m_size;
}
//清空链表
void clear_LinkList(LList linList) {
if (linList == NULL)
return;
struct LinkList* list = linList;
struct LinkNode* pcurrentNode = list->pHeader.next;
for (int i = 0; i < list->m_size;i++)
{
struct LinkNode* pNext = pcurrentNode->next;
free(pcurrentNode);
pcurrentNode = pNext;
}
list->m_size = 0;
list->pHeader.next = NULL;
}
//销毁链表
void destroy_LinkList(LList linklist) {
if (linklist == NULL)
return;
clear_LinkList(linklist);
free(linklist);
linklist = NULL;
}
//测试
typedef struct Person {
char name[64];
int age;
}Person;
void myPrint(void* data) {
Person* p = data;
printf("姓名= %s, 年龄= %d\n", p->name, p->age);
}
int myCompare(void* d1, void* d2) {
Person* p1 = d1;
Person* p2 = d2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
void test01() {
Person p1 = { "bobo",22 };
Person p2 = { "hoho",23 };
Person p3 = { "gogo",24 };
Person p4 = { "yoyo",25 };
//初始化链表并返回一个链表
LList* list = init_linkList();
//插入链表
insert_linkList(list, 1, &p1);
insert_linkList(list, 0, &p2);
insert_linkList(list, -2, &p3);
insert_linkList(list, 3, &p4);
//遍历链表
for_each_LinkList(list, myPrint);
printf("链表的长度为:%d\n", get_size_LinkList(list));
printf("==============\n");
//按位置去删除一个节点
delete_LinkList_pos(list, 0);
for_each_LinkList(list, myPrint);
printf("链表的长度为:%d\n", get_size_LinkList(list));
//按值去删除一个节点
printf("==============\n");
Person p5 = { "yoyo",25 };
delete_LinkList_value(list, &p5, myCompare);
for_each_LinkList(list, myPrint);
printf("链表的长度为:%d\n", get_size_LinkList(list));
//清空链表
clear_LinkList(list);
//printf("链表的长度为:%d\n", get_size_LinkList(list));
//销毁链表
destroy_LinkList(list);
//printf("链表的长度为:%d", get_size_LinkList(list));
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
C语言实现单向链表的初始化、按值插入、按位置插入、删除、清空、销毁等操作
最新推荐文章于 2024-05-02 18:02:39 发布