【数据结构与算法】单向链表
文章目录
- 【数据结构与算法】单向链表
- 前言
- 一、单向链表初始化
- 二、单向链表插入与遍历
- 三、单向链表的删除与清空
- 四、单向链表返回长度以及销毁
- 五、完整代码
- 六、单向链表企业版
- 总结
前言
本篇文章就单向链表初始化,插入遍历功能,链表删除,清空,返回长度以及销毁。单向链表企业版初始化,插入,遍历,删除和销毁实现。
一、单向链表初始化
单向链表初始化
//结点结构体
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;
}
//将list还原成 struct LList 数据类型
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;
}
//pCurrent 要插入节点的前驱
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->data = data;
newNode->next = NULL;
//建立节点关系
newNode->next = pCurrent->next;
pCurrent->next = newNode;
//更新链表长度
myList->m_size++;
}
遍历链表
//遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void*))
{
if (list == NULL)
{
return;
}
struct LList* mylist = list;
struct LinkNode* pCurrent = mylist->pHeader.next;
for (int i = 0; i < mylist->m_size; i++)
{
myForeach(pCurrent->data);
pCurrent = pCurrent->next;
}
}
测试:
//测试
struct Person
{
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("姓名:%s, 年龄: %d\n", p->name, p->age);
}
void test01()
{
//准备数据
struct Person p1 = { "亚瑟", 18 };
struct Person p2 = { "妲己", 20 };
struct Person p3 = { "安琪拉", 19 };
struct Person p4 = { "凯", 21 };
struct Person p5 = { "孙悟空", 999 };
struct Person p6 = { "李白", 999 };
//初始化链表
LinkList mylist = init_LinkList();
//插入数据
insert_LinkList(mylist, 0, &p1);
insert_LinkList(mylist, 0, &p2);
insert_LinkList(mylist, -1, &p3);
insert_LinkList(mylist, 0, &p4);
insert_LinkList(mylist, 1, &p5);
insert_LinkList(mylist, 0, &p6);
//遍历
foreach_LinkList(mylist, myPrintPerson);
}
int main() {
test01();
return 0;
}
三、单向链表的删除与清空
按位置删除
//删除链表 按位置
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*, void*))
{
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++)
{
//pCurrent->data data 将两个指针比较利用回调 交给用户
if (myCompare(pCurrent->data, data))
{
pPrev->next = pCurrent->next;
free(pCurrent);
pCurrent = NULL;
mylist->m_size--;
break;
}
//辅助指针后移
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
}
测试:
//测试
struct Person
{
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("姓名:%s, 年龄: %d\n", p->name, p->age);
}
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;
}
void test01()
{
//准备数据
struct Person p1 = { "亚瑟", 18 };
struct Person p2 = { "妲己", 20 };
struct Person p3 = { "安琪拉", 19 };
struct Person p4 = { "凯", 21 };
struct Person p5 = { "孙悟空", 999 };
struct Person p6 = { "李白", 999 };
//初始化链表
LinkList mylist = init_LinkList();
//插入数据
insert_LinkList(mylist, 0, &p1);
insert_LinkList(mylist, 0, &p2);
insert_LinkList(mylist, -1, &p3);
insert_LinkList(mylist, 0, &p4);
insert_LinkList(mylist, 1, &p5);
insert_LinkList(mylist, 0, &p6);
//遍历
foreach_LinkList(mylist, myPrintPerson);
//测试删除
removeByPos_LinkList(mylist, 4);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
struct Person p = { "孙悟空", 999 };
removeByValue_LinkList(mylist, &p, myComparePerson);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
}
清空链表
//清空链表
void clear_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;
}
四、单向链表返回长度以及销毁
返回链表长度
//返回链表长度
int size_LinkList(LinkList list)
{
if (list == NULL)
{
return -1;
}
struct LList* mylist = list;
return mylist->m_size;
}
销毁链表
//销毁链表
void destroy_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
//清空链表
clear_LinkList(list);
free(list);
list = NULL;
}
测试:
//测试
struct Person
{
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("姓名:%s, 年龄: %d\n", p->name, p->age);
}
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;
}
void test01()
{
//准备数据
struct Person p1 = { "亚瑟", 18 };
struct Person p2 = { "妲己", 20 };
struct Person p3 = { "安琪拉", 19 };
struct Person p4 = { "凯", 21 };
struct Person p5 = { "孙悟空", 999 };
struct Person p6 = { "李白", 999 };
//初始化链表
LinkList mylist = init_LinkList();
//插入数据
insert_LinkList(mylist, 0, &p1);
insert_LinkList(mylist, 0, &p2);
insert_LinkList(mylist, -1, &p3);
insert_LinkList(mylist, 0, &p4);
insert_LinkList(mylist, 1, &p5);
insert_LinkList(mylist, 0, &p6);
//遍历
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
//测试删除
removeByPos_LinkList(mylist, 4);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
struct Person p = { "孙悟空", 999 };
removeByValue_LinkList(mylist, &p, myComparePerson);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
//测试清空
clear_LinkList(mylist);
//返回链表长度
printf("链表长度为:%d\n", size_LinkList(mylist));
//销毁
destroy_LinkList(mylist);
mylist = NULL;
printf("链表长度为:%d\n", size_LinkList(mylist));
}
五、完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#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;
}
//将list还原成 struct LList 数据类型
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;
}
//pCurrent 要插入节点的前驱
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->data = data;
newNode->next = NULL;
//建立节点关系
newNode->next = pCurrent->next;
pCurrent->next = newNode;
//更新链表长度
myList->m_size++;
}
//遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void*))
{
if (list == NULL)
{
return;
}
struct LList* mylist = list;
struct LinkNode* pCurrent = mylist->pHeader.next;
for (int i = 0; i < mylist->m_size; i++)
{
myForeach(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*, void*))
{
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++)
{
//pCurrent->data data 将两个指针比较利用回调 交给用户
if (myCompare(pCurrent->data, data))
{
pPrev->next = pCurrent->next;
free(pCurrent);
pCurrent = NULL;
mylist->m_size--;
break;
}
//辅助指针后移
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
}
//清空链表
void clear_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;
}
//返回链表长度
int size_LinkList(LinkList list)
{
if (list == NULL)
{
return -1;
}
struct LList* mylist = list;
return mylist->m_size;
}
//销毁链表
void destroy_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
//清空链表
clear_LinkList(list);
free(list);
list = NULL;
}
//测试
struct Person
{
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("姓名:%s, 年龄: %d\n", p->name, p->age);
}
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;
}
void test01()
{
//准备数据
struct Person p1 = { "亚瑟", 18 };
struct Person p2 = { "妲己", 20 };
struct Person p3 = { "安琪拉", 19 };
struct Person p4 = { "凯", 21 };
struct Person p5 = { "孙悟空", 999 };
struct Person p6 = { "李白", 999 };
//初始化链表
LinkList mylist = init_LinkList();
//插入数据
insert_LinkList(mylist, 0, &p1);
insert_LinkList(mylist, 0, &p2);
insert_LinkList(mylist, -1, &p3);
insert_LinkList(mylist, 0, &p4);
insert_LinkList(mylist, 1, &p5);
insert_LinkList(mylist, 0, &p6);
//遍历
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
//测试删除
removeByPos_LinkList(mylist, 4);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
struct Person p = { "孙悟空", 999 };
removeByValue_LinkList(mylist, &p, myComparePerson);
printf("------------------\n");
foreach_LinkList(mylist, myPrintPerson);
printf("链表长度为:%d\n", size_LinkList(mylist));
//测试清空
clear_LinkList(mylist);
//返回链表长度
printf("链表长度为:%d\n", size_LinkList(mylist));
//销毁
destroy_LinkList(mylist);
mylist = NULL;
printf("链表长度为:%d\n", size_LinkList(mylist));
}
int main() {
test01();
return 0;
}
六、单向链表企业版
完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//节点结构体
struct LinkNode
{
//只维护指针域
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.next = NULL;
myList->m_Size = 0;
}
//插入
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 - 1)
{
//无效位置进行尾插
pos = myList->m_Size;
}
//用户数据的前4个字节 由我们来使用
struct LinkNode* myNode = data;
//找插入节点的前驱节点
struct LinkNode* pCurrent = &myList->pHeader;
for (int i = 0; i < pos; i++)
{
pCurrent = pCurrent->next;
}
//pCurrent是前驱节点位置
//更新指针指向
myNode->next = pCurrent->next;
pCurrent->next = myNode;
//更新链表长度
myList->m_Size++;
}
//遍历链表
void foreach_LinkList(LinkList list, void(*myForeach)(void*))
{
if (list == NULL)
{
return;
}
struct LList* myList = list;
struct LinkNode* myNode = myList->pHeader.next;
for (int i = 0; i < myList->m_Size; i++)
{
myForeach(myNode);
myNode = myNode->next;
}
}
//删除节点 按位置删除
void removeByPos_LinktList(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); //数据是用户管理开辟的,用户管理释放
//更新长度
mylist->m_Size--;
}
//销毁链表
void destroy_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
free(list);
list = NULL;
}
//测试
struct Person
{
void* node;
char name[64];
int age;
};
void myPrintPerson(void* data)
{
struct Person* p = data;
printf("姓名: %s 年龄: %d \n", p->name, p->age);
}
void test01()
{
//初始化链表
LinkList mylist = init_LinkList();
//创建数据
struct Person p1 = { NULL,"aaa", 10 };
struct Person p2 = { NULL,"bbb", 20 };
struct Person p3 = { NULL,"ccc", 30 };
struct Person p4 = { NULL,"ddd", 40 };
struct Person p5 = { NULL,"eee", 50 };
//插入节点
insert_LinkList(mylist, 0, &p1);
insert_LinkList(mylist, 0, &p2);
insert_LinkList(mylist, 1, &p3);
insert_LinkList(mylist, -1, &p4);
insert_LinkList(mylist, 0, &p5);
//遍历链表
// eee bbb ccc aaa ddd
foreach_LinkList(mylist, myPrintPerson);
//删除 aaa
removeByPos_LinktList(mylist, 3);
printf("-----------------------\n");
foreach_LinkList(mylist, myPrintPerson);
//销毁数组
destroy_LinkList(mylist);
mylist = NULL;
}
int main() {
test01();
return 0;
}
总结
到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!