使用万能指针实现通用链表
前面通过地址偏移量计算结构体成员变量首地址,来访问结构体里的成员。现在,我们将通过使用万能指针来实现通用链表,使得链表可以存储任意类型的数据。
废话不多说,直接上代码
#list.h
#ifndef list_h
#define list_h
#include<stdbool.h>
#include<stdio.h>
typedef int (*compar)(const void*,const void*);
//结点
typedef struct node
{
void *ptr;
struct node *prev;
struct node *next;
}node;
//通用链表
typedef struct list
{
node *head;
size_t size;
}list;
//创建
list *create_list(void);
//添加
void add_list(list *list,void *ptr);
//插入
bool insert_list(list *list,size_t index,void *ptr);
//删除 按位置
bool del_index_list(list *list,size_t index);
//删除 按值
bool del_value_list(list *list,void *ptr,compar cmp);
//查询
void *query_list(list *list,void *ptr,compar cmp);
//访问
void *visit_list(list *list,size_t index);
//遍历
void show_list(list *list,void (*show)(void*));
//排序
void sort_list(list *list,compar cmp);
//清空
void clean_list (list *list);
//销毁
void destroy_list(list *list);
#endif//list_h
#list.c
#include<stdlib.h>
#include<stdio.h>
#include"list.h"
//创建结点
static node *create_node(void *ptr)
{
node *node=malloc(sizeof(node));
node->ptr=ptr;
node->prev=node;
node->next=node;
return node;
}
//创建
list *create_list(void)
{
list *list=malloc(sizeof(list));
list->head=create_node(0);
list->size=0;
return list;
}
//两节点间插入新结点
void _add_list(node *prev,node *next,void *ptr)
{
node *node=create_node(ptr);
prev->next=node;
node->next=next;
next->prev=node;
node->prev=prev;
}
//根据位置访问结点
static node *_visit_list(list *list,size_t index)
{
if(index<0||index>=list->size)return null;
if(index>list->size/2)
{
node *node=list->head->prev;
while(++index<list->size)node=node->prev;
return node;
}
else
{
node *node=list->head->next;
while(index--)node=node->next;
return node;
}
}
//删除结点
static void _del_list(node *node)
{
node->prev->next=node->next;
node->next->prev=node->prev;
free(node->ptr);
free(node);
}
//尾添加
void add_list(list *list,void *ptr)
{
_add_list(list->head->prev,list->head,ptr);
list->size++;
}
//插入
bool insert_list(list *list,size_t index,void *ptr)
{
node *node=_visit_list(list,index);
if(null==node)return false;
_add_list(node->prev,node,ptr);
list->size++;
return true;
}
//删除 按位置
bool del_index_list(list *list,size_t index)
{
node *node=_visit_list(list,index);
if(null==node)return false;
_del_list(node);
list->size--;
return true;
}
//删除 按值
bool del_value_list(list *list,void *ptr,compar cmp)
{
for(node *n=list->head->next;n!=list->head;n=n->next)
{
if(0==cmp(ptr,n->ptr))
{
_del_list(n);
list->size--;
return true;
}
}
return false;
}
//查询
void *query_list(list *list,void *ptr,compar cmp)
{
for(node *n=list->head->next;n!=list->head;n=n->next)
{
if(0==cmp(ptr,n->ptr))
{
return n->ptr;
}
}
return null;
}
//访问
void *visit_list(list *list,size_t index)
{
node *n=_visit_list(list,index);
if(null==n)return false;
return n->ptr;
}
//遍历
void show_list(list *list,void (*show)(void*))
{
for(node *node=list->head->next;node!=list->head;node=node->next)
{
show(node->ptr);
}
}
//排序
void sort_list(list *list,compar cmp)
{
for(node *n=list->head->next;n!=list->head;n=n->next)
{
for(node *m=n->next;m!=list->head;m=m->next)
{
if(1==cmp(n->ptr,m->ptr))
{
void *temp=n->ptr;
n->ptr=m->ptr;
m->ptr=temp;
}
}
}
}
//清空
void clean_list (list *list)
{
node *n=list->head->next;
while(n!=list->head)
{
node *temp=n;
n=n->next;
free(temp);
}
list->head->next=list->head;
list->head->prev=list->head;
list->size=0;
}
//销毁
void destroy_list(list *list)
{
clean_list(list);
free(list->head);
free(list);
}
#main.c
#include <stdio.h>
#include<stdlib.h>
#include"list.h"
typedef struct student
{
char name[20];
char sex;
int id;
}student;
void show_stu(void *ptr)
{
student *stu=ptr;
printf("name:%s sex:%c id:%d \n",stu->name,stu->sex,stu->id);
}
int stucmp(const void *p1,const void *p2)
{
const student *s1=p1,*s2=p2;
if(s1->id>s2->id)
{
return 1;
}
else if(s1->id<s2->id)
return -1;
else return 0;
}
int main(int argc,const char* argv[])
{
list *list=create_list();
for(int i=0;i<10;i++)
{
student *stu=malloc(sizeof(student));
sprintf(stu->name,"浩楠%d",i);
stu->sex=i%2?'w':'m';
stu->id=1000-i;
add_list(list,stu);
}
show_list(list,show_stu);
student s={"刘浩1",'m',1001};
insert_list(list,5,&s);
sort_list(list,stucmp);
printf("------------------\n");
show_list(list,show_stu);
return 0;
}
通过以上代码示例,我们实现了一个通用链表,可以存储任意类型的数据。通过使用函数指针和万能指针,我们实现了对不同类型数据的存储和操作。这种通用链表的设计可以在实际开发中提供更大的灵活性和可扩展性。
发表评论