数据结构——通用链表

本文介绍了通用链表的数据结构,包括链表节点定义、常用操作(如创建、添加、删除、查询、排序等),并提供了示例代码,展示了如何在链表中插入、删除、查询学生数据,并进行排序。

通用链表

结点:

    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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyu1381

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值