之前的链表就是一个普通的带头的单向链表,我们不自觉的会发现这样的链表有缺陷,有关链表的删除新增查找跟链表的结构体内容耦合性太强
什么意思呢?
比如我们之前的链表的结构体
typedef struct_Teacher
{intage;struct _Teacher *next;
}Teacher;
我们有关链表所有的操作都跟这个结构体紧密的相连,如果此刻我们有另一个结构体,里面的字段都跟这个不一样,那么,我们可能还需要对这个新的结构体写一套链表操作?
相当于下面的图,呵呵,有点丑
那么我们的解决方案是什么呢?,我们能不能关于不同结构体的所有操作都有一套公共方法呢?
当然是可以的!
在这之前我们必须有一个概念,结构体中的第一个元素的地址就是代表结构体的地址。
我们设计一个单纯代表数据结构的结构体,这个结构体只有下个对象的地址的指针成员
typedef struct_tag_LinkListNode
{void *next;
}LinkListNode;
比如此刻我们有一个教师结构体,那么我们只需要在结构体的第一个成员是上面的LinkListNode对象。
形成下面的数据结构:
typedef struct_Teacher
{
LinkListNode listNode;intage;char name[50];
}Teacher;
那么,此刻我们只要在我们的对链表的操作将传过来的Teacher * 指针强转为LinkListNode *类型,查询出来的LinkListNode * 指针变量再强转为Teacher * 对象,从而对LinkListNode形成一套插入删除查询的api就可以了
以下是实现的代码:
接口:
#ifndef _MYLINKLIST_H_#define _MYLINKLIST_H_typedefvoidLinkList;
typedefstruct_tag_LinkListNode
{struct _tag_LinkListNode*next;
}LinkListNode;
LinkList*LinkList_Create();void LinkList_Destroy(LinkList*list);void LinkList_Clear(LinkList*list);int LinkList_Length(LinkList*list);int LinkList_Insert(LinkList* list, LinkListNode* node, intpos);
LinkListNode* LinkList_Get(LinkList* list, intpos);
LinkListNode* LinkList_Delete(LinkList* list, intpos);#endif
实现:
#include "stdio.h"#include"stdlib.h"#include"linklist.h"typedefstruct_tag_LinkList
{//头节点
LinkListNode header;intlength;
}TLinkList;/************************************************************************/
/*创建list并初始化一个头节点*/
/************************************************************************/LinkList*LinkList_Create()
{
TLinkList*tlist = (TLinkList *)malloc(sizeof(TLinkList));if (tlist ==NULL)
{returnNULL;
}
tlist->length = 0;
tlist->header.next =NULL;returntlist;
}void LinkList_Destroy(LinkList*list)
{if (list ==NULL)
{return;
}free(list);
}/************************************************************************/
/*清空list链表*/
/************************************************************************/
void LinkList_Clear(LinkList*list)
{if (list ==NULL)
{return;
}
TLinkList*tlinkList = (TLinkList *)list;
tlinkList->length = 0;
tlinkList->header.next =NULL;
}int LinkList_Length(LinkList*list)
{if (list ==NULL)
{return 0;
}
TLinkList*tlinkList = (TLinkList *)list;return tlinkList->length;
}int LinkList_Insert(LinkList* list, LinkListNode* node, intpos)
{
LinkListNode*pre, *cur;inti;if (list == NULL || node ==NULL)
{return -1;
}//校验下标
if (pos<0)
{return -2;
}
TLinkList*tlinkList = (TLinkList *)list;if (pos>tlinkList->length - 1)
{
pos= tlinkList->length;
}
pre= (LinkListNode *)list;//初始化指向头节点
cur = tlinkList->header.next;//初始化指向第一个节点,如果空链表指向空
for (i = 0; i < pos; i++)
{
pre=cur;
cur= cur->next;//最终让当前指针指向要插入的位置
}
pre->next =node;
node->next =cur;
tlinkList->length++;return 0;
}
LinkListNode* LinkList_Get(LinkList* list, intpos)
{
LinkListNode*pre, *cur;inti;if (list ==NULL)
{returnNULL;
}
TLinkList*tlinkList = (TLinkList *)list;//校验下标
if (pos >= tlinkList->length || pos < 0)
{returnNULL;
}
cur= tlinkList->header.next;//初始化指向第一个节点,如果空链表指向空
for (i = 0; i < pos; i++)
{
cur= cur->next;
}returncur;
}
LinkListNode* LinkList_Delete(LinkList* list, intpos)
{
LinkListNode*pre, *cur;inti;if (list ==NULL)
{returnNULL;
}
TLinkList*tlinkList = (TLinkList *)list;//校验下标
if (pos >= tlinkList->length || pos < 0)
{returnNULL;
}
pre= (LinkListNode *)list;//初始化指向头节点
cur = tlinkList->header.next;//初始化指向第一个节点,如果空链表指向空
for (i = 0; i < pos; i++)
{
pre=cur;
cur= cur->next;
}
pre->next = cur->next;
LinkListNode* curnode =cur;
tlinkList->length--;returncurnode;
}
测试代码
#include "stdio.h"#include"stdlib.h"#include"linklist.h"typedefstruct_Teacher
{
LinkListNode listNode;intage;char name[50];
}Teacher;voidmain()
{
LinkList*linkList;
Teacher t1, t2, t3;intlen;inti;
linkList=LinkList_Create();
t1.age= 11;
t2.age= 22;
t3.age= 33;
LinkList_Insert(linkList, (LinkListNode*)&t1, 0);
LinkList_Insert(linkList, (LinkListNode*)&t2, 0);
LinkList_Insert(linkList, (LinkListNode*)&t3, 0);
len=LinkList_Length(linkList);for (i = 0; i < len; i++)
{
Teacher* t = (Teacher *)LinkList_Get(linkList, i);
printf("cur teacher age=%d", t->age);
}
LinkList_Delete(linkList,0);
LinkList_Delete(linkList,1);
len=LinkList_Length(linkList);for (i = 0; i < len; i++)
{
Teacher* t = (Teacher *)LinkList_Get(linkList, i);
printf("cur teacher age=%d", t->age);
}
system("pause");
}
接下来,如果我们有新的结构体,只要在测试代码那边做修改,而不需要动我们的核心代码了。