链表是由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--;
}