通用双向链表 思想以及代码

  前两天实现了一个通用双向链表,期间有很多地方有感悟,所以就把过程以及代码记录了下来。

  一个双向链表的定义一般是struct List{struct List * pre,struct List * next};如果我们随意定义一个链表(由于是通用的)只要我们定义如下struct MyList{struct MyList *pre,struct MyList *next ,~}
那样的话,我们可以把自己定义的链表结构强制转换成List类型,那样的话,pre,next由于位置,大小一样,我们对强制转换成的List以后的指针操作就相当于对MyList进行操作了,可以实现链表的插入删除了,但是我们如何进行排序,查找,这些跟自定义的链表又具体关系的操作呢?
  这就可以通过函数指针进行了,比如我们定义了一个学生链表,我们要查找其中年龄为20的学生,我们可以定义如下一个函数 int Find_Stu(struct Stu *s){if (s->age==20) return 1}这个时候,如果我们在通用链表中把这个函数指针传递过去,然后把链表节点的指针强制转换成了Stu的指针,然后就可以用这个函数查找了,来完成相应的功能,这就完成了通用链表到具体链表的操作应用!
下面是我的代码:
  Sturct.h
typedef struct List
{
 struct List *pre;
 struct List *next;
}List,*pList;
typedef struct List{  struct List *pre;  struct List *next;}List,*pList;
  List.h
#include "Struct.h"
#include "string.h"
#include "malloc.h"
void Init_List(pList* pLhead,pList *pLtaile)
{
(*pLhead)=(pList)malloc(sizeof(List));
(*pLhead)->next=(*pLhead);
(*pLhead)->pre=(*pLhead);
(*pLtaile)=(*pLhead);
}
int Add_a_Node(pList * pLhead,pList *pLtaile,void *node,void *node_B_A,int n)
{
pList nowNode=(pList)node;
pList B_A_node=(pList)node_B_A;
if(n==1)//往后面插入
{
if(B_A_node==(*pLtaile))
{
nowNode->pre=(*pLtaile);
(*pLtaile)->next=nowNode;
(*pLtaile)=nowNode;
(*pLtaile)->next=(*pLhead);
}
else
{
nowNode->next=B_A_node->next;
nowNode->pre=B_A_node;
B_A_node->next=nowNode;
nowNode->next->pre=nowNode;
}
return 0;
}
else if(n==0)//往前插入节点 
{
if(B_A_node==(*pLhead))
{
nowNode->next=(*pLhead)->next;
nowNode->pre=(*pLhead);
(*pLhead)->next=nowNode;
nowNode->next->pre=nowNode;
if((*pLhead)==(*pLtaile))
{
(*pLtaile)=nowNode;
(*pLtaile)->next=(*pLhead);
(*pLhead)->pre=(*pLtaile);
}
}
else
{
nowNode->next=B_A_node;
nowNode->pre=B_A_node->pre;
B_A_node->pre=nowNode;
nowNode->pre->next=nowNode;
}(*pLhead)->pre=(*pLtaile);
return 0;
}
return -1;//输入参数有错
}
void * Search_A_node(pList Lhead,int (*p) (void *))
{
pList OneList;
for(OneList=Lhead->next;OneList!=Lhead;OneList=OneList->next)
{
if(p(OneList)==1)
return OneList;
}
return NULL;
}
int All_Se(pList Lhead,pList Ltaile,void (*p)(void *),int n)//n==1从头指针往后遍历,否则从尾指针往前遍历
{
pList now;
if(n==1)
{
for(now=Lhead->next;now!=Lhead;now=now->next)
p(now);
return 0;
}
else
{
for(now=Ltaile;now->pre!=Ltaile;now=now->pre)
p(now);
return 0;
}
return -1;
}
int To_Node(pList Lhead)
{
pList now;
int i=0;
for(now=Lhead->next;now!=Lhead;now=now->next)
i++;
return i;
}
void * Fine_One(pList Lhead,int n)
{
int i=0;
pList Now=Lhead;
if(n<=To_Node(Lhead))
{
for(i=0;i<n;i++)
Now=Now->next;
return Now;
}
return NULL;
}
int switchL(pList Lhead,pList Ltaile,pList PL1,pList PL2)
{
pList PList1,PList2,PList3,PList4;
if(PL2==Ltaile)
{
Ltaile=PL1;
PList1=PL1->pre;
PList2=PL1;
PList3=PL2;
PList2->next=Lhead;
PList2->pre=PList3;
PList3->next=PList2;
PList3->pre=PList1;
PList1->next=PList3;
if(PList1==Lhead)
{
Lhead->pre=Ltaile;
}
return 0;
}
else
{
PList1=PL1->pre;
PList2=PL1;
PList3=PL2;
PList4=PL2->next;
PList1->next=PList3;
PList2->next=PList4;
PList2->pre=PList3;
PList3->next=PList2;
PList3->pre=PList1;
PList4->pre=PList2;
return 0;
}
}
int SortList(pList Lhead,pList Ltaile,int (*p)(void *,void *))
{
int num=To_Node(Lhead),i,j,real;
pList PL1,PL2;
for(i=0;i<=num&&num>1;i++)
   {
    real=0;
for(j=1;j<num;j++)
{
PL1=(pList)Fine_One(Lhead,j);
PL2=(pList)Fine_One(Lhead,j+1);
if(p(PL1,PL2))
{
         real=1;
switchL(Lhead,Ltaile,PL1,PL2);
}
}
    if(real==0) return 0;
  }
return 0;
}
int Merge(pList *PLhead1,pList *PLtaile1,pList *PLhead2,pList *PLtaile2)
{
if((*PLhead2)==(*PLtaile2))
{
return 0;
}
else
{
(*PLtaile1)->next=(*PLhead2)->next;
(*PLhead2)->next->pre=(*PLtaile1);
(*PLtaile2)->next=(*PLhead1);
(*PLhead1)->pre=(*PLtaile2);
(*PLtaile1)=(*PLtaile2);
(*PLhead2)->pre=(*PLhead2);
(*PLhead2)->next=(*PLhead2);
(*PLtaile2)=(*PLhead2);
return 0;
}
return -1;
}
int  Dele_List(pList *PLhead,pList *PLtaile)
{
// pList now;
// for(now=(*PLhead)->next;now!=(*PLhead);now=now->next)
// {
// free(now);
// }
(*PLhead)->pre=(*PLhead);
(*PLhead)->next=(*PLhead);
(*PLtaile)=(*PLhead);
}
  在编写这个程序的时候还学到了如下一些东西:
1.不论我们引用系统库多少次,都不会引起重定义问题,但是自己写的库却常常有这个问题我们可以用宏
#ifndef MMM 
#define MMM 
内容 
#endif
这样我们自己写的库也只会被加载一遍了。
2.函数指针的使用

转载于:https://www.cnblogs.com/husttianya/articles/1780113.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值