单链表各种操作实现(数据结构C语言多文件编写)

1. 先创建list.h声明文件( Linux 命令:touch list.h)。编写函数声明如下(打开文件 Linux 操作命令:vim list.h):

cpp 复制代码
//链表头文件
#ifndef __LIST_H__
#define __LIST_H__
//节点
typedef struct node{
    int data;//数据
    struct node* next;//下个节点地址
}node_t;

//链表
typedef struct list{
    node_t* head;//记录头结点地址
    node_t* tail;//记录尾节点地址
}list_t;

//链表初始化
void list_init(list_t* l);
//链表的释放
void list_deinit(list_t* l);
//头部插入节点
void list_insert_head(list_t* l,int data);
//尾部插入节点
void list_insert_tail(list_t* l,int data);
//链表顺序插入
void list_insert(list_t* l,int data);
//删除节点
void list_del(list_t* l,int data);
//链表的遍历
void list_travel(list_t* l);
#endif //__LIST_H__

2. 创建函数实现文件list.c( Linux 命令:touch list.c)。写入函数到文件中:

cpp 复制代码
//链表实现
#include<stdio.h>
#include"list.h"
#include<stdlib.h>

//链表的初始化

void list_init(list_t* l){
    //创建头结点,地址存入head指针
    l->head=malloc(sizeof(node_t));
    //创建尾节点,地址存入tail指针
    l->tail=malloc(sizeof(node_t));
    //讲0存入头尾节点
    l->head->data=0;
    l->tail->data=0;
    
    //头尾节点相连
    l->head->next=l->tail;
    l->tail->next=NULL;
}

//链表的释放
void list_deinit(list_t* l){
    node_t* pnode=l->head;
    while(pnode){
        //tmp 存储下个节点的地址
        node_t* tmp=pnode->next;
        //释放pnode指向的节点
        free(pnode);
        //pnode指向下一个节点
        pnode=tmp;
    }
    l->head=NULL;
    l->tail=NULL;
}
//头部插入
void list_insert_head(list_t* l,int data){
    //准备新节点
    node_t* new=malloc(sizeof(node_t));
    new->data=data;
    new->next=NULL;
    //将新节点插入到节点之后
    //将第一个有效节点的地址 存入 新节点的next 指针
    new->next=l->head->next;
    //将新节点的地址 存入 头结点的 next指针
    l->head->next=new;
}
//尾部插入
void list_insert_tail(list_t* l,int data){
    //准备新节点
    node_t* new= malloc(sizeof(node_t));
        
    new->data=data;
    new->next=NULL;

    for(node_t *p=l->head;p!=l->tail;p->next){
        node_t* first=p;
        node_t* mid=first->next;

        if(mid==l->tail){
            //当mid指向尾节点
            //first 指向最后有效节点
            //新节点插入在 firat和mid指向的节点之间
            //将新节点的地址 存入 first指向节点的next指针
            first->next=new;
            //将尾节点的地址存入
            new->next=mid;
            break;
        }
    }
}
//顺序插入
void list_insert(list_t* l,int data){
    //准备新节点
    node_t* new=malloc(sizeof(node_t));
    new->data=data;
    new->next=NULL;
    //确定位置并插入新节点
    for(node_t* p=l->head;p!=l->tail;p=p->next){
        node_t* first=p;
        node_t* mid=first->next;

        //当mid指向的节点,第一次比新节点大
        //或者mid指向尾节点说明节点最大
        //新节点则应该插入在first和mid指向的节点中间
        if(mid->data>new->data||mid==l->tail){
            //将新节点的地址存入first指向节点的next指针中
            first->next=new;
            //将mid指向节点的地址存入新节点的next指针中
            new->next=mid;
            break;
        }
    }
}
//删除节点
void list_del(list_t* l,int data){
    node_t* first;
    node_t* mid;
    node_t* last;
    for(node_t* p=l->head;p!=l->tail;p=p->next){
        first=p;
        mid=first->next;
        last=mid->next;
        if(mid->data==data){
            first->next=last;
            free(mid);
            break;
        }
    }
    if(mid ==l->tail){
        printf("节点不存在\n");
    }
}
//链表的遍历
void list_travel(list_t* l){
    for(node_t* p=l->head->next;p!=l->tail;p=p->next){
        printf("%d ",p->data);
    }
    printf("\n");
}

3. 编写主函数调用文件main.c(Linux命令:touch main.c)。编写逻辑操作:

cpp 复制代码
//链表的实现
#include<stdio.h>
#include"list.h"
int main(void){
    //链表
    list_t list;
    printf("初始化\n");
    list_init(&list);
    printf("头部插入节点\n");
    list_insert_head(&list,30);
    list_insert_head(&list,20);
    list_insert_head(&list,20);
    printf("尾部插入节点\n");
    list_insert(&list,70);
    list_insert(&list,40);
    list_insert(&list,90);
    list_insert(&list,50);
    list_insert(&list,110);
    printf("遍历\n");
    list_travel(&list);
    printf("释放链表\n");
    list_deinit(&list);
    return 0;
}

**4.**编译运行

Linux命令:gcc main.c queue.c -o queue

运行:./queue

相关推荐
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假5 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠6 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦13 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园14 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob14 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
小小工匠14 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
源分享14 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm