开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情
前言
以前参与一个蓝牙电话本的项目,不同的手机实现的电话簿关键字各个不同,测试的人会加上几十万的联系人,所以一个排序和链表是必不可少的。当初用一个单向链表保存了全部的联系人,本人尝试实现双向链表数据结构。
接口
一个简单的结构图如下所示
许多链表的实现上,头节点作为起始节点,不存在有效数据;有的实现上头节点作为实际有效的节点。但在实现上和可理解程度上,头节点单纯作为起始节点,代码实现会更简单,代码会少许多麻烦,比起浪费一个节点的空间缺点来说,值得。
结构体
typedef struct LL{
struct LL *fNode;
struct LL *nNode;
}DUALIST ,*DUALISTPtr;
typedef struct{
DUALISTPtr CuNode;
int key;
int var ;
}MYLST,*MYLSTPtr;
接口:
- 新节点添加链表头 Add2Head
- 新节点添加链表尾 Add2Tail
- 删除节点,接口主键使用的整数 DelNode
- 修改数据, ChgVal
- 清空链表 ClearLst
- 遍历节点,我一般用来打印全部信息 IterateLst
代码实例
想着按照Linux内核链表实现方案,把链表结构和应用数据结构做结解耦,提出一些接口,应用数据部分结构随意更改。
无奈个人水平太差,查找功能接口如何和链表方案的解耦方案不会。所以实例代码里链表结构和应用数据在一起实现。
这样逻辑,此链表少了许多通用型,过些日子再回来修改,继续优化一点。
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef void (*func)(int a,int b);
typedef struct LL{
struct LL *fNode;
struct LL *nNode;
int key;
int var ;
}MYLST,*MYLSTPtr;
#define INITLIST(v,t) do{ v = (t*)malloc(sizeof(t));memset(v,0,sizeof(t));v->fNode = v->nNode = v; }while(0)
int Add2Head(MYLSTPtr Hd,MYLSTPtr v)
{
MYLSTPtr tt = Hd;
MYLSTPtr tt2 = v;
//修改原第二节点和新点的相互指向
tt2->nNode = tt->nNode;
tt->nNode->fNode = tt2;
//修改头节点和新点的相互指向
tt2->fNode = tt;
tt->nNode = tt2;
return 0;
}
int Add2Tail(MYLSTPtr Hd,MYLSTPtr v)
{
MYLSTPtr Head = Hd;
MYLSTPtr NewNd = v;
//修改原尾节点和新点的相互指向
Head->fNode->nNode = NewNd;
NewNd->fNode = Head->fNode;
//修改头节点和新点的相互指向
NewNd->nNode = Head;
Head->fNode = NewNd;
return 0;
}
int DelNode(MYLSTPtr Hd,int key)
{
MYLSTPtr Head = Hd;
MYLSTPtr FirNode = Head->nNode;
int ret = 0;
while(FirNode != Head){
FirNode = FirNode->nNode;
if(key == FirNode->key){
FirNode->nNode->fNode = FirNode->fNode;
FirNode->fNode->nNode = FirNode->nNode;
free(FirNode);
ret = 1;
break;
}
}
return ret;
}
int ChgVal(MYLSTPtr Hd,int key,int val)
{
MYLSTPtr Head = Hd;
MYLSTPtr FirNode = Head->nNode;
int ret = 0;
while(FirNode != Head){
FirNode = FirNode->nNode;
if(key == FirNode->key){
FirNode->var = val;
ret = 1;
break;
}
} return 0;
}
int ClearLst(MYLSTPtr Hd)
{
MYLSTPtr temp = Hd;
Hd->fNode->nNode = NULL;
while(Hd){
temp = Hd;
Hd = Hd->nNode;
free(temp);
}
return 0;
}
//dir= 1 正向
//dir= 0 反向
int IterateLst(MYLSTPtr Hd,func fPtr,int dir)
{
MYLSTPtr Head = Hd;
MYLSTPtr FirNode = dir==1? Head->nNode:Head->fNode;
while(FirNode != Head){
if(fPtr) fPtr(FirNode->key,FirNode->var);
FirNode = dir==1? FirNode->nNode:FirNode->fNode;
}
return 0;
}
void printfall(int key, int val)
{
printf("key[%d] val[%d]\n",key,val);
}
int main(int argc, char** argv)
{
int cnt = 0;
MYLSTPtr Head;
INITLIST(Head,MYLST);
MYLSTPtr MyNode = NULL;
while(cnt < 100){
MyNode = (MYLSTPtr)malloc(sizeof(MYLST));
MyNode->key = MyNode->var = cnt;
MyNode->fNode = MyNode->nNode = NULL;
Add2Head(Head,MyNode);
cnt++;
}
IterateLst(Head,printfall,1);
ClearLst(Head);
Head = NULL;
return 0;
}
测试结果