面向用户的单向链表
此链表面向用户,用户在定义数据时预留出指针位置,开发人员操作时仅仅操作用户的前四个内存位置 ,可大大提高效率!
例如:
typedef struct Person{
//预留出四个字节的指针
//预留的目的是开发人员进行维护链表指针
void *node;//预留出指针位置
char name[64];
int age;
}Person;
模型展示
代码实现展示
** 注释非常详细可直接编译运行**
//
// Created by wen on 2021/9/18.
//企业级开发单向链表
//
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
//定义节点结构
typedef struct LinkNode {
//只维护指针域
struct LinkNode *next;
}LinkNode;
//定义链表结构
typedef struct LList{
LinkNode pHeader;
int m_size;
}LList;
//不想让用户直接拿到链表
typedef void * LinkList;
//初始化链表
LinkList * init_LinkList(){
LList *myList = malloc(sizeof (LList));
if(myList==NULL){
return 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;
}
//还原链表结构
LList * myList = List;
//判断位置是否正确,不正确位置进行尾插
if(pos<0||pos>myList->m_size-1)
{
pos = myList->m_size;
}
//企业级开发,开发人员仅仅维护用户前四个字节
LinkNode* myNode = data;
//找插入节点的前驱节点
LinkNode * pCurrent = &(myList->pHeader);
//使用for循环一步一步找前驱节点
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 (*foreach_print)(void *)){
if(List==NULL)
{
return;
}
//还原链表结构体
LList *myList =List;
//找到有数据的那个结点
LinkNode * myNode = myList->pHeader.next;
//进行遍历
for (int i = 0; i <myList->m_size ; ++i) {
//因为只传出地址,故需要回调函数
foreach_print(myNode);
//指针偏移
myNode = myNode->next;
}
}
//删除
//按位置进行删除
void DeleteByPos_Linklist(LinkList List, int pos){
if(List==NULL){
return;
}
//还原链表
LList * myList = List;
//删除位置不正确判断
if(pos<0||pos>myList->m_size-1)
{
return;
}
//遍历找前驱指针
LinkNode *pCurrent = &myList->pHeader;
//开始遍历
for (int i = 0; i < pos;++i)
{
pCurrent= pCurrent->next;
}
//pcurrent 为前驱,记录一下待删除的节点
LinkNode *pre_node = pCurrent->next;
//更改指针指向
pCurrent->next = pre_node->next;
//注意
//不能直接写free(),因为数据是用户给的,我们只维护前四个空间,不知道用户是在哪里开辟的数据
//让用户自己去释放
//更新链表长度
myList->m_size--;
}
//按照值进行删除
void DeleteByValue_LinkList(LinkList List, void *data ,int (*Compare)(void* ,void *)){
if(List ==NULL)
{
return;
}
if(data ==NULL){
return;
}
LList *myList = List;
LinkNode * pCurrent = &myList->pHeader;
//储存删除的元素
LinkNode *pDel = pCurrent->next;
for (int i = 0; i < myList->m_size; ++i) {
if(Compare(pDel,data))
{
//更新节点关系
pCurrent->next = pDel->next;
//更新链表长度
myList->m_size -- ;
break;
}
//指针后移
pCurrent = pDel;
pDel= pDel->next;
}
myList->m_size--;
}
//清空就是把链表全部断
//数据用户自己释放
void clear_LinkList(LinkList List){
if(List == NULL)
{
return;
}
//还原链表
LList * myList = List;
LinkNode * pCurrent = &myList->pHeader;
for (int i = 0; i <myList->m_size ; ++i) {
LinkNode * prev= pCurrent->next;
pCurrent ==NULL;
pCurrent = prev;
}
//更新
myList->pHeader.next = NULL;
myList->m_size=0;
}
//销毁
void destroy_LinkList(LinkList List){
if(List == NULL)
{
return;
}
free(List);
List ==NULL;
printf("销毁成功\n");
}
//____________________________________________________________________________________
//测试
typedef struct Person{
//预留出四个字节的指针
//预留的目的是开发人员进行维护链表指针
void *node;
char name[64];
int age;
}Person;
//打印函数(回调函数)
void print_Person(void *data){
Person *P1 = data;
printf("name:%s,age:%d\n",P1->name,P1->age);
}
//值比较的回调函数
int PersonCompare(void *data1 , void * data2){
Person *p1 =data1;
Person *p2 =data2;
return strcmp(p1->name,p2->name)==0 && p1->age == p2->age;
}
//test为测试函数
void test() {
//初始化
LinkList *myList = init_LinkList();
//测试数据
Person P1 = {NULL,"tom1", 1};
Person P2 = {NULL,"tom2", 2};
Person P3 = {NULL,"tom3", 3};
Person P4 = {NULL,"tom4", 4};
Person P5 = {NULL,"tom5", 5};
Person P6 = {NULL,"tom6", 6};
Person P7 = {NULL,"tom7", 7};
Person P8 = {NULL,"tom8", 8};
Person P9 = {NULL,"tom9", 9};
Person P10 = {NULL,"tom10", 10};
Person a[10]={P1,P2,P3,P4,P5,P6,P7,P8,P9,P10};
//插入
for (int i=0; i<10;i++){
insert_LinkList(myList,0,a+i);
}
//遍历链表
foreach_LinkList(myList,print_Person);
//位置删除
DeleteByPos_Linklist(myList,2);
printf("del_byPos\n");
foreach_LinkList(myList,print_Person);
//按照值来删除
DeleteByValue_LinkList(myList,&P6,PersonCompare);
// clear_LinkList(myList);
printf("del_byValue\n");
foreach_LinkList(myList,print_Person);
//销毁
destroy_LinkList(myList);
myList == NULL;
}
void main(){
test();
}