一、思路:针对线性表的链式存储,其实我们最主要的是要考虑如何将链表节点和业务节点如何合在一起,意思就是我们的链表的API函数,操作的是链表节点,而我们如何将业务节点和链表节点相绑定,这样的话,这样的话我们操作链表节点,其实就是操作的业务节点。
二.通用链表:链表操作还是只操作链表节点,但是链表节点存在业务节点的开始,那么链表节点和业务节点的地址就是相通的,这样可以将业务节点伪装成链表节点。如图所示:
三.对于通用链表模型的删除和插入数据,模型图
四、链表的相关API函数:
头文件定义为:
#ifndef __SEQLIST__H
#define __SEQLIST__H
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct _list_node
{
struct _list_node *pnext;
}list_node;
typedef struct _seqlist
{
list_node header;
int length;
} seqlist;
seqlist* seqlist_create(int cap);
int seqlist_length(seqlist *seq);
list_node * seqlist_get(seqlist *seq,int n);
int seqlist_insert(seqlist *seq,list_node *node,int n);
list_node *seqlist_delete(seqlist *seq,int n);
#endif
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "seqlist.h"
seqlist* seqlist_create()
{
seqlist *tmp = NULL;
int ret = 0;
tmp = malloc(sizeof(seqlist));
if(NULL == tmp)
{
ret = -1;
printf("seqlist_create error :%d \n",ret);
return NULL;
}
tmp->length = 0;
tmp->header.pnext = NULL;
return tmp;
}
int seqlist_capacity(seqlist *seq)
{
int ret = 0;
if(NULL ==seq)
{
ret = -1;
printf("seqlist_capacity error :%d \n",ret);
return ret;
}
return seq->capacity;
}
int seqlist_length(seqlist *seq)
{
int ret = 0;
if(NULL == seq)
{
ret = -1;
printf("seqlist_length error :%d \n",ret);
return ret;
}
return seq->length;
}
list_node * seqlist_get(seqlist *seq,int n)
{
int ret =0,i = 0;
if(NULL == seq)
{
ret = -1;
printf("seqlist_get error :%d \n",ret);
return NULL;
}
if(seq->length <=0)
{
ret = -3;
printf("seqlist_get error :%d \n",ret);
return NULL;
}
if(n > seq->length -1)
{
ret = -2;
printf("seqlist_get error :%d \n",ret);
return NULL;
}
list_node * pcurrent = NULL;
pcurrent = (list_node *)seq;
for(i =0;i <= n;i++)
{
pcurrent = pcurrent->pnext;
}
return pcurrent;
}
int seqlist_insert(seqlist *seq,list_node *node,int n)
{
int i = 0 ,ret = 0;
if(NULL == seq || NULL == node || n<0)
{
ret = -1;
printf("seqlist_insert errpr :%d \n",ret);
return ret;
}
list_node * pcurrent = (list_node *)seq;
for(i = 0; i < n;i++)
{
pcurrent = pcurrent->pnext;
}
if(n == seq->length) //对于尾部插入也有个特殊处理
{
pcurrent ->pnext = node;
seq->length++;
node->pnext = NULL;
return ret;
}
seq->length++;
node->pnext = pcurrent->pnext;
pcurrent->pnext = node;
return ret;
}
list_node *seqlist_delete(seqlist *seq,int n)
{
int i =0,ret = 0;
if(NULL == seq || n<0 || n>=seq->length)
{
ret = -1;
printf("seqlist_delete error :%d \n",ret);
return NULL;
}
list_node * pcurrent = (list_node *)seq;
for(i = 0;i < n;i++)
{
pcurrent = pcurrent->pnext;
}
if(n == seq->length -1) //对于尾部删除有个特殊处理
{
list_node *tmp = pcurrent->pnext;
pcurrent->pnext = NULL;
seq->length--;
return tmp;
}
list_node *tmp = pcurrent->pnext;
pcurrent->pnext = pcurrent->pnext->pnext;
seq->length--;
return tmp;
}
总结:
1.链表通用模型关键点在于:将链表节点和业务节点想绑定,通过C语言的指针强制类型转换来实现的;
2.链表的删除和插入,主要关键在于定义一个辅助指针,通过这个辅助指针来实现相关的业务逻辑,这也是比较关键的