C语言实现一个链表

链表是由N个节点离散组合而成的,节点由两部分组成(数据域+指针域)
每个节点通过指针链接,
每个节点都拥有一个前驱节点和一个后驱节点
首节点的前驱节点为空,尾节点的后驱节点为空

数据结构
typedef struct Node
{
    void *data;
    struct Node *next;
}Node;

typedef struct List
{
    Node head;//头结点
    int size;// 节点个数
}List;

//函数指针,指向一个函数 ,其返回类型为void ,函数参数为void *
typedef void(*print_data)(void *data);

API:
1.初始化链表
2.销毁链表
3.指定位置插入链表
4.获取链表的节点个数
5.获取链表的元素
6.指定位置删除
7.打印链表

void * init_list(void);
void destroy_list(void * list);
void insert_list_by_pos(void *list, int pos, void *data);
int get_list_size(void *list);
void *get_list_by_pos(void *list, int pos);
void remove_list_by_pos(void *list, int pos);
void print_list(void *list, print_data print);

创建链表
void * init_list(void)
{
    List *p = (List *)malloc(sizeof(List));
    if(p == NULL)
    {
        ptintf("malloc list * err!\n");
        exit(1);
    }
    p->head.next = NULL;
    p->size = 0;
    return p;
}
销毁链表

借助 del 与tmp指针来销毁
del指针指向首节点
tmp指针指向尾节点的后驱节点

Node *del = p->head.next;
Node *tmp = NULL;

通过移动tmp指针来确定下一个要删除的节点点
del指针删完毕后再指向下一个节点
直至del 与tmp指针都指向空
这里写图片描述

void destroy_list(void *list)
{
    if(list == NULL)
    {
        return;
    }
    List *p =(List *)list;
    //释放头节点后面的节点
    Node *del = p->head.next;
    //tmp 用来保存头节点
    Node *tmp = NULL;
    while(del != tmp)
    {
        tmp = del->next;
        free(del);
        del  = tmp;
    }
    if( p!= NULL)
    {
        free(p);
        p = NULL;
    }
    printf("destroy list finished\n!");
}
指定位置插入链表

借助tmp指针
先获取需要插入节点的上一个节点,断开上一个节点的next指针,指向新节点pnew,pnew->next指向tmp->next
这里写图片描述


void  insert_list_by_post(void *list,int pos,void *data)
{
    if(list == NULL || data == NULL)
    {
        return;
    }
    List * p =(List *)list;
    if(pos < 0|| pos >p->size)
    {
        pos = p->size;
    }
    //辅助指针
    Node *tmp=&p->head;
    int i ;
    //获取需要插入节点的上一个节点
    for(i = 0;i < pos;i++)
    {
        tmp = tmp->next;
    }
    //新建节点
    Node * pnew = (Node *)malloc(sizeof(Node));
    if(pnew == NULL)
    {
        printf("malloc pnew err!\n");
        exit(1);
    }
    pnew->data = data;
    //新节点指向下一个节点
    pnew->next = tmp->next;
    tmp->next =pnew;
    p->size++;

}
获取链表的节点个数
int get_list_size(void *list)
{
    if(list == NULL)
    {
        return -1;
    }
    List *p = (List *)list;
    return p->size;
}
获取指定位置的元素
void *get_list_by_pos(void *list,int pos)
{
    if(list == NULL )
    {
        return NULL;
    }
    List *p = (List *)list;
    if(pos < 0|| pos >p->size)
    {
        printf("pos err!\n");
        return NULL;
    }
    //tmp获取指定位置的节点上一个节点
    Node *tmp =&p->head;
    int i;
    for(i = 0;i< pos;i++)
    {
        tmp = tmp->next;
    }
    return tmp->next->data;
}
删除指定位置的节点
void remove_list_by_pos(void *list,int pos)
{
    if( list == NULL)
    {
        return;
    }
    List *p = (List *)list;
    if(pos < 0 || pos > p->size)
    {
        printf("pos err!\n");
        return;
    }
    //tmp为需要删除节点的上一个节点
    Node *tmp = &p->head;
    int i ;
    for(i = 0;i< pos;i++)
    {
        tmp= tmp->next;
    }

    Node *del = tmp->next;
    if(del == NULL)
    {
        return;
    }
    tmp->next= del->next;
    free(del);
    del= NULL;
    p->size--;
}
打印链表

print_data 是一个typedef 的函数指针

void print_list(void *list,print_data print)
{
    if(list == NULL || print == NULL)
    {
        return;
    }
    List *p = (List *)list;
    Node *tmp = &p->head;
    int i ;
    for(i = 0;i < p->size;i++)
    {
        print(tmp->data);
        tmp=tmp->next;
    }
}
结尾删除
void push_back(void *list)
{
    if (list == NULL)
    {
        return;
    }
    List *p = (List *)list;

    Node *tmp = &p->head;
    int i;
    for (i = 0; i < p->size - 1 ; i++)
    {
        tmp = tmp->next;
    }
    Node *del = tmp->next;
    if(del == NULL)
    {
        printf("del NULL\n");
        return;
    }
    tmp->next = NULL;
    free(del);
    del = NULL;
    p->size--;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值