LINUX多文件实现双链表(C语言)附带Makefile

主函数测试代码

#include"list.h"

int main()
{
    list_t list;
    list_init(&list);
    list_add(&list,10);
    list_add(&list,20);
    list_add(&list,30);
    list_add_head(&list,40);
    list_add_tail(&list,50);
    list_travel(&list);
    printf("%d\n",list_size(&list));
    list_del_first(&list);
    list_travel(&list);
    printf("%d\n",list_size(&list));
    list_del_tail(&list);
    list_travel(&list);
    printf("%d\n",list_size(&list));
    printf("%d\n",list_get(&list,2));
    list_deinit(&list);
    return 0;
}

头文件声明代码

// 双链表头文件
#ifndef __LIST_H
#define __LIST_H
#include<stdio.h>
#include<stdlib.h>
//定义节点结构体
typedef struct node
{
    int data;//数据
    struct node *next;//保存下一个节点地址
    struct node *prev;//保存上一个节点地址
}node_t;
//定义链表结构体
typedef struct list
{
    struct node head;//头节点
    struct node tail;//尾节点
}list_t;

//初始化
extern void list_init(list_t *list);
//释放内存
extern void list_deinit(list_t *list);
//插入数据
extern void list_add(list_t *list,int data);
//头插
extern void list_add_head(list_t *list,int data);
//尾插
extern void list_add_tail(list_t *list,int data);
//遍历
extern void list_travel(list_t *list);
//删除指定数据节点
extern void list_del(list_t *list,int data);
//判断是否为空
extern int list_empty(list_t *list);
//获取有效数据个数
extern int list_size(list_t *list);
//只删除第一个有效节点
extern void list_del_first(list_t *list);
//只删除最后一个有效节点
extern void list_del_tail(list_t *list);
//根据节点编号获取节点数据
extern int list_get(list_t *list,int index);
#endif

函数实现代码

#include"list.h"
//定义创建节点函数
static node_t * creat_node(int data)
{
    node_t *pnew = (node_t *)malloc(sizeof(node_t));
    pnew->data = data;
    pnew->next = NULL;
    pnew->prev = NULL;
    return pnew;
}
//初始化
extern void list_init(list_t *list)
{
    list->head.prev = NULL;
    list->head.next = &list->tail;
    list->tail.prev = &list->head;
    list->tail.next = NULL;
    list->head.data = 0;
    list->tail.data = 0;
}
//释放内存
extern void list_deinit(list_t *list)
{
    while(list->head.next != &list->tail)
    {
        node_t *pfirst = &list->head;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        pfirst->next = plast;
        plast->prev = pfirst;
        free(pmid);
        break;
    }
}
//插入数据
extern void list_add(list_t *list,int data)
{
    //创建新节点
    node_t *pnew = creat_node(data);
    //遍历链表
    for(node_t * pnode = &list->head;pnode != &list->tail;
            pnode = pnode->next)
    {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid->data >= pnew->data || 
                pmid == &list->tail)
            {
                pfirst->next = pnew;
                pnew->prev = pfirst;
                pnew->next = pmid;
                pmid->prev = pnew;
            }
    }
}
//头插
extern void list_add_head(list_t *list,int data)
{
    node_t * pnew = creat_node(data);
    node_t * pfirst = &list->head;
    node_t * pmid = pfirst->next;
    pfirst->next = pnew;
    pnew->prev = pfirst;
    pnew->next = pmid;
    pmid->prev = pnew;
}
//尾插
extern void list_add_tail(list_t *list,int data)
{
    node_t *pnew = creat_node(data);
    node_t *pmid = &list->tail;
    node_t *pfirst = pmid->prev;
    pfirst->next = pnew;
    pnew->prev = pfirst;
    pnew->next = pmid;
    pmid->prev = pnew;
}
//遍历
extern void list_travel(list_t *list)
{  
    for(node_t *pnode = &list->head;pnode != &list->tail;
            pnode = pnode->next)
    {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid != &list->tail)
        {
            printf("%d ",pmid->data);
        }
    }
}
//删除
extern void list_del(list_t *list,int data)
{
    for(node_t *pnode = &list->head;pnode != &list->tail;
            pnode = pnode->next)
    {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid->data == data && pmid != &list->tail)
        {
            pfirst->next = plast;
            plast->prev = pfirst;
            free(pmid);
            break;
        }
    }

}
//判断是否为空
extern int list_empty(list_t *list)
{
    return list->head.next == &list->tail;
    //空返回1否则返回0
}
//获取有效数据个数
extern int list_size(list_t *list)
{
    int count = 0;//记录有效节点个数
    for(node_t *pnode = &list->head;pnode != &list->tail;
            pnode = pnode->next)
    {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(pmid != &list->tail)
        {
            count++;//更新计数
        }
    }
    return count;
}
//只删除第一个有效节点
extern void list_del_first(list_t *list)
{
    if(list_empty(list))
    {
        printf("链表空了\n");
        return;
    }
    node_t *pfirst = &list->head;
    node_t *pmid = pfirst->next;
    node_t *plast = pmid->next;
    pfirst->next = plast;
    plast->prev = pfirst;
    free(pmid);
    //break;

}
//只删除最后一个有效节点
extern void list_del_tail(list_t *list)
{
    if(list_empty(list))
    {
        printf("链表空了\n");
        return;
    }
    node_t *plast = &list->tail;
    node_t *pmid = plast->prev;
    node_t *pfirst = pmid->prev;
    pfirst->next = plast;
    plast->prev = pfirst;
    free(pmid);
    //break;
}
//根据节点编号获取节点数据
extern int list_get(list_t *list,int index)
{
    if(index > list_size(list) - 1)
    {
        printf("超出数据范围");
        return -1;
    }
    int count= 0;
    for(node_t *pnode = &list->head;
            pnode != &list->tail;
            pnode = pnode->next)
    {
        node_t *pfirst = pnode;
        node_t *pmid = pfirst->next;
        node_t *plast = pmid->next;
        if(count == index && pmid != &list->tail)
        {
            return pmid->data;
        }
        count++;
    }
}

Make file文件内容:注意回车和tab

BIN=list
OBJ=main.o list.o
CC=gcc

$(BIN):$(OBJ)
    $(CC) -o $(BIN) $(OBJ)

%.o:%.c
    $(CC) -c -o $@ $<

clean:
    rm $(BIN) $(OBJ)
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值