1.先创建list.h声明文件( Linux 命令:touch list.h)。编写函数声明如下(打开文件 Linux 操作命令:vim list.h):
//链表头文件
#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)。写入函数到文件中:
//链表实现
#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)。编写逻辑操作:
//链表的实现
#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 list.c -o list
运行:./list