通用链表
结点:
void* ptr
指针域
运算:常规功能+回调函数
list.h
#ifndef LIST_H
#define LIST_H
#include <stdio.h>
#include <stdbool.h>
// 重定义了函数指针类型 新类型名叫Comper
// 定义函数指针变量 Comper cmp
// cmp即函数指针变量
typedef int (*Comper)(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_head_list(List* list,void* ptr);
// 尾添加
void add_tail_list(List* list,void* ptr);
// 插入
bool insert_list(List* list,size_t index,void* ptr);
// 按位置删除
void* del_index_list(List* list,size_t index);
// 按值删除
void* del_value_list(List* list,void* ptr,
int (*cmp)(const void*,const void*));
// 查询
void* query_list(List* list,void* ptr,Comper cmp);
// 访问
void* access_list(List* list,size_t index);
// 排序
void sort_list(List* list,Comper cmp);
// 清空
void clear_list(List* list);
// 销毁
void destory_list(List* list);
// 遍历
void show_list(List* list,void (*show)(void*));
#endif//LIST_H
list.c
#include <stdlib.h>
#include "list.h"
// 创建结点
static Node* create_node(void* ptr)
{
Node* node = malloc(sizeof(Node));
node->next = node;
node->prev = node;
node->ptr = ptr;
return node;
}
// 根据位置访问结点
static Node* _index_list(List* list,size_t index)
{
if(index >= list->size) return NULL;
if(index < list->size/2)
{
Node* n = list->head->next;
while(index--) n = n->next;
return n;
}
else
{
Node* n = list->head->prev;
while(++index < list->size) n = n->prev;
return n;
}
}
// 在两个结点之间插入一个结点
static void _add_list(Node* prev,Node* next,void* ptr)
{
Node* node = create_node(ptr);
prev->next = node;
node->prev = prev;
next->prev = node;
node->next = next;
}
// 删除结点
static void* _del_list(Node* node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
void* p = node->ptr;
free(node);
return p;
}
// 创建链表 带头结点
List* create_list(void)
{
List* list = malloc(sizeof(List));
list->head = create_node(NULL);
list->size = 0;
return list;
}
// 头添加
void add_head_list(List* list,void* ptr)
{
_add_list(list->head,list->head->next,ptr);
list->size++;
}
// 尾添加
void add_tail_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 = _index_list(list,index);
if(NULL == node) return false;
_add_list(node->prev,node,ptr);
list->size++;
return true;
}
// 按位置删除
void* del_index_list(List* list,size_t index)
{
Node* node = _index_list(list,index);
if(NULL == node) return NULL;
list->size--;
return _del_list(node);
}
// 按值删除
void* del_value_list(List* list,void* ptr,
int (*cmp)(const void*,const void*))
{
for(Node* n=list->head->next; list->head!=n; n=n->next)
{
if(0 == cmp(ptr,n->ptr))
{
list->size--;
return _del_list(n);
}
}
return NULL;
}
// 查询
void* query_list(List* list,void* ptr,Comper 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* access_list(List* list,size_t index)
{
Node* node = _index_list(list,index);
if(NULL == node) return NULL;
return node->ptr;
}
// 排序
void sort_list(List* list,Comper cmp)
{
for(Node* i=list->head->next; list->head!=i->next; i=i->next)
{
for(Node* j=i->next; list->head!=j; j=j->next)
{
if(0 > cmp(i->ptr,j->ptr))
{
void* temp = i->ptr;
i->ptr = j->ptr;
j->ptr = temp;
}
}
}
}
// 清空 用户的数据必须存储在堆内存
void clear_list(List* list)
{
Node* node = list->head->next;
while(node != list->head)
{
Node* temp = node;
node = node->next;
free(temp->ptr);
free(temp);
}
list->head->next = list->head;
list->head->prev = list->head;
list->size = 0;
}
// 销毁
void destory_list(List* list)
{
clear_list(list);
free(list->head);
free(list);
}
// 遍历 show是回调函数 由调用者提供
void show_list(List* list,void (*show)(void*))
{
for(Node* n=list->head->next; list->head!=n; n=n->next)
{
show(n->ptr);
}
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
typedef struct Student
{
char name[20];
char sex;
int id;
}Student;
// 函数返回值 参数列表 要与调用的函数中的函数指针参数完全一致
void show_stu(void* ptr)
{
Student* stu = ptr;
printf("姓名:%s 性别:%c 学号:%d\n",stu->name,stu->sex,stu->id);
}
// 比较函数
int cmp_id(const void* p1,const void* p2)
{
const Student *s1 = p1,*s2 = p2;
if(s1->id > s2->id) return -1;
if(s1->id < s2->id) return 1;
return 0;
}
int cmp_name(const void* p1,const void* p2)
{
const Student *s1 = p1,*s2 = p2;
return strcmp(s1->name,s2->name);
}
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,"hehe%d",i);
stu->sex = i%2?'w':'m';
stu->id = 1000+i;
add_head_list(list,stu);
}
Student stu1 = {"hehe5",'w',1003};
Student stu2 = {"ooo",'w',1004};
// insert_list(list,1,&stu1);
free(del_index_list(list,0));
free(del_index_list(list,8));
free(del_index_list(list,2));
free(del_value_list(list,&stu1,cmp_id));
free(del_value_list(list,&stu1,cmp_name));
Student* s = query_list(list,&stu2,cmp_id);
show_list(list,show_stu);
printf("---%s %c %d---\n",s->name,s->sex,s->id);
strcpy(s->name,"xixi");
show_list(list,show_stu);
printf("================\n");
sort_list(list,cmp_id);
show_list(list,show_stu);
destory_list(list);
}
本文介绍了通用链表的数据结构,包括链表节点定义、常用操作(如创建、添加、删除、查询、排序等),并提供了示例代码,展示了如何在链表中插入、删除、查询学生数据,并进行排序。

1941

被折叠的 条评论
为什么被折叠?



