一、思路:針對線性表的鏈式存儲,其實我們最主要的是要考慮如何將鏈表節點和業務節點如何合在一起,意思就是我們的鏈表的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.鏈表的刪除和插入,主要關鍵在於定義一個輔助指針,通過這個輔助指針來實現相關的業務邏輯,這也是比較關鍵的