双向循环链表
带头结点的双向循环链表
插入的操作:
基础代码:
- llist.c文件代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "llist.h"
LLIST *llist_create(int initsize)
{
LLIST *new;
new=malloc(sizeof(*new));
if(new==NULL)
{
return NULL;
}
new->size=initsize;
new->head.data=NULL;
new->head.prev=&new->head;
new->head.next=&new->head;
return new;
}
void llist_destroy(LLIST *ptr)
{
struct llist_node_st *cur,*next;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
{
next=cur->next;
free(cur->data);
free(cur);
}
free(ptr);
}
int llist_insert(LLIST *ptr,const void *data,int mode)
{
struct llist_node_st *newnode;
newnode=malloc(sizeof(*newnode));
if(newnode==NULL)
return -1;
newnode->data=malloc(ptr->size);
if(newnode->data==NULL)
return -2;
memcpy(newnode->data,data,ptr->size);
if(mode==LLIST_FORWARD)
{
newnode->prev=&ptr->head;
newnode->next=ptr->head.next;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else if(mode==LLIST_BACKWARD)
{
newnode->prev=ptr->head.prev;
newnode->next=&ptr->head;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else
{
return -3;
}
return 0;
}
static struct llist_node_st *find_(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
if(cmp(key,cur->data)==0)
break;
}
return cur;
}
/*
llist_delete();
llist_fetch();
*/
int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
free(node->data);
free(node);
return 0;
}
int llist_fetch(LLIST *ptr,const void *key,llist_cmp*cmp,void *data)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
if(data != NULL)
{
memcpy(data,node->data,ptr->size);
}
free(node->data);
free(node);
return 0;
}
void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
return find_(ptr,key,cmp)->data;
}
void llist_show(LLIST *ptr,llist_op *op)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
op(cur->data);
}
}
- llist.h文件代码:
#ifndef LLIST_H__
#define LLIST_H__
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
struct llist_node_st
{
void *data;
struct llist_node_st *prev;
struct llist_node_st *next;
};
typedef struct LLIST
{
int size;
struct llist_node_st head;
}LLIST;
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);
int llist_insert(LLIST *,const void *data,int mode);
int llist_delete(LLIST *,const void *key,llist_cmp *);
void *llist_find(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp*,void *data);
void llist_show(LLIST *,llist_op *);
#endif
- main.c文件代码:
#include <stdio.h>
#include <stdlib.h>
#include "llist.h"
#define NAMESIZE 32
struct score_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};
void print_s(const void *record)
{
const struct score_st *r=record;
printf("%d %s %d %d \n",r->id,r->name,r->math,r->chinese);
}
static int id_cmp(const void *key,const void *record)
{
const int *k=key;
const struct score_st *r=record;
return (*k-r->id);
}
int main()
{
int i;
LLIST *handler;
struct score_st tmp;
handler=llist_create(sizeof(struct score_st));
/*if err*/
for(i=0;i<7;i++)
{
tmp.id=i;
snprintf(tmp.name,NAMESIZE,"std%d",i);
tmp.math=rand()%100;
tmp.chinese=rand()%100;
llist_insert(handler,&tmp,LLIST_BACKWARD);
}
llist_show(handler,print_s);
printf("\n \n");
int id=3;
struct score_st *data;
llist_delete(handler,&id,id_cmp);
llist_show(handler,print_s);
data=llist_find(handler,&id,id_cmp);
if(data==NULL)
{
printf("sorry ,can not find.\n");
}
else
{
print_s(data);
}
llist_destroy(handler);
exit(0);
}
- makefile文件内容:
all:llist
llist:llist.o main.o
$(CC) $^ -o $@
clean:
rm llist *.o -rf
利用变长结构体来实现双向循环链表的实现
- llist.c文件代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "llist.h"
LLIST *llist_create(int initsize)
{
LLIST *new;
new=malloc(sizeof(*new));
if(new==NULL)
{
return NULL;
}
new->size=initsize;
new->head.prev=&new->head;
new->head.next=&new->head;
return new;
}
void llist_destroy(LLIST *ptr)
{
struct llist_node_st *cur,*next;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
{
next=cur->next;
free(cur);
}
free(ptr);
}
int llist_insert(LLIST *ptr,const void *data,int mode)
{
struct llist_node_st *newnode;
newnode=malloc(sizeof(*newnode) + ptr->size);
if(newnode==NULL)
return -1;
memcpy(newnode->data,data,ptr->size);
if(mode==LLIST_FORWARD)
{
newnode->prev=&ptr->head;
newnode->next=ptr->head.next;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else if(mode==LLIST_BACKWARD)
{
newnode->prev=ptr->head.prev;
newnode->next=&ptr->head;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else
{
return -3;
}
return 0;
}
static struct llist_node_st *find_(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
if(cmp(key,cur->data)==0)
break;
}
return cur;
}
int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
free(node);
return 0;
}
int llist_fetch(LLIST *ptr,const void *key,llist_cmp*cmp,void *data)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
if(data != NULL)
{
memcpy(data,node->data,ptr->size);
}
free(node);
return 0;
}
void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return NULL;
return node->data;
}
void llist_show(LLIST *ptr,llist_op *op)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
op(cur->data);
}
}
- llist.h文件代码实现:
#ifndef LLIST_H__
#define LLIST_H__
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
struct llist_node_st
{
struct llist_node_st *prev;
struct llist_node_st *next;
char data[1];
};
typedef struct LLIST
{
int size;
struct llist_node_st head;
}LLIST;
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);
int llist_insert(LLIST *,const void *data,int mode);
int llist_delete(LLIST *,const void *key,llist_cmp *);
void *llist_find(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp*,void *data);
void llist_show(LLIST *,llist_op *);
#endif
其他文件不变。
用C语言实现面向对象的思想:
将函数的入口地址,包含在结构体当中。
- llist.c文件内容:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "llist.h"
int llist_insert(LLIST *,const void *data,int mode);
int llist_delete(LLIST *,const void *key,llist_cmp *);
void *llist_find(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp*,void *data);
void llist_show(LLIST *,llist_op *);
LLIST *llist_create(int initsize)
{
LLIST *new;
new=malloc(sizeof(*new));
if(new==NULL)
{
return NULL;
}
new->size=initsize;
new->head.prev=&new->head;
new->head.next=&new->head;
new->insert=llist_insert;
new->delete=llist_delete;
new->find=llist_find;
new->fetch=llist_fetch;
new->show=llist_show;
return new;
}
void llist_destroy(LLIST *ptr)
{
struct llist_node_st *cur,*next;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
{
next=cur->next;
free(cur);
}
free(ptr);
}
int llist_insert(LLIST *ptr,const void *data,int mode)
{
struct llist_node_st *newnode;
newnode=malloc(sizeof(*newnode) + ptr->size);
if(newnode==NULL)
return -1;
memcpy(newnode->data,data,ptr->size);
if(mode==LLIST_FORWARD)
{
newnode->prev=&ptr->head;
newnode->next=ptr->head.next;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else if(mode==LLIST_BACKWARD)
{
newnode->prev=ptr->head.prev;
newnode->next=&ptr->head;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else
{
return -3;
}
return 0;
}
static struct llist_node_st *find_(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
if(cmp(key,cur->data)==0)
break;
}
return cur;
}
/*
llist_delete();
llist_fetch();
*/
int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
free(node);
return 0;
}
int llist_fetch(LLIST *ptr,const void *key,llist_cmp*cmp,void *data)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
if(data != NULL)
{
memcpy(data,node->data,ptr->size);
}
free(node);
return 0;
}
void *llist_find(LLIST *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return NULL;
return node->data;
}
void llist_show(LLIST *ptr,llist_op *op)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
op(cur->data);
}
}
- llist.h文件内容
#ifndef LLIST_H__
#define LLIST_H__
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
struct llist_node_st
{
struct llist_node_st *prev;
struct llist_node_st *next;
char data[1];
};
typedef struct llist_head
{
int size;
struct llist_node_st head;
int (*insert)(struct llist_head *,const void *,int);
void *(*find)(struct llist_head *,const void *,llist_cmp *);
int (*delete)(struct llist_head *,const void *,llist_cmp *);
int (*fetch)(struct llist_head *,const void *,llist_cmp *,void *);
void (*show)(struct llist_head *,llist_op *);
}LLIST;
LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);
#endif
- main.c文件内容
#include <stdio.h>
#include <stdlib.h>
#include "llist.h"
#define NAMESIZE 32
struct score_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};
void print_s(const void *record)
{
const struct score_st *r=record;
printf("%d %s %d %d \n",r->id,r->name,r->math,r->chinese);
}
static int id_cmp(const void *key,const void *record)
{
const int *k=key;
const struct score_st *r=record;
return (*k-r->id);
}
int main()
{
int i;
int ret;
LLIST *handler;
struct score_st tmp;
handler=llist_create(sizeof(struct score_st));
/*if err*/
for(i=0;i<7;i++)
{
tmp.id=i;
snprintf(tmp.name,NAMESIZE,"std%d",i);
tmp.math=rand()%100;
tmp.chinese=rand()%100;
ret=handler->insert(handler,&tmp,LLIST_BACKWARD);
if(ret)
{
exit(1);
}
}
handler->show(handler,print_s);
#if 0
printf("\n \n");
int id=3;
struct score_st *data;
llist_delete(handler,&id,id_cmp);
llist_show(handler,print_s);
data=llist_find(handler,&id,id_cmp);
if(data==NULL)
{
printf("sorry ,can not find.\n");
}
else
{
print_s(data);
}
#endif
llist_destroy(handler);
exit(0);
}
其他文件不变。
接下来将数据结构进行隐藏和封装,让用户看不到当前实现的数据结构,但是可以实现链表。
- llist.c文件内容:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "llist.h"
struct llist_node_st
{
struct llist_node_st *prev;
struct llist_node_st *next;
char data[1];
};
struct llist_head_st
{
int size;
struct llist_node_st head;
};
LLIST *llist_create(int initsize)
{
struct llist_head_st *new;
new=malloc(sizeof(*new));
if(new==NULL)
{
return NULL;
}
new->size=initsize;
new->head.prev=&new->head;
new->head.next=&new->head;
return new;
}
void llist_destroy(LLIST *p)
{
struct llist_head_st *ptr=p;
struct llist_node_st *cur,*next;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
{
next=cur->next;
free(cur);
}
free(ptr);
}
int llist_insert(LLIST *p,const void *data,int mode)
{
struct llist_node_st *newnode;
struct llist_head_st *ptr=p;
newnode=malloc(sizeof(*newnode) + ptr->size);
if(newnode==NULL)
return -1;
memcpy(newnode->data,data,ptr->size);
if(mode==LLIST_FORWARD)
{
newnode->prev=&ptr->head;
newnode->next=ptr->head.next;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else if(mode==LLIST_BACKWARD)
{
newnode->prev=ptr->head.prev;
newnode->next=&ptr->head;
newnode->prev->next=newnode;
newnode->next->prev=newnode;
}
else
{
return -3;
}
return 0;
}
static struct llist_node_st *find_(struct llist_head_st *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
if(cmp(key,cur->data)==0)
break;
}
return cur;
}
int llist_delete(LLIST *p,const void *key,llist_cmp *cmp)
{
struct llist_head_st *ptr=p;
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
free(node);
return 0;
}
int llist_fetch(LLIST *p,const void *key,llist_cmp*cmp,void *data)
{
struct llist_head_st *ptr=p;
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
{
return -1;
}
node->prev->next=node->next;
node->next->prev=node->prev;
if(data != NULL)
{
memcpy(data,node->data,ptr->size);
}
free(node);
return 0;
}
void *llist_find(LLIST *p,const void *key,llist_cmp *cmp)
{
struct llist_head_st *ptr=p;
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return NULL;
return node->data;
}
void llist_show(LLIST *p,llist_op *op)
{
struct llist_head_st *ptr=p;
struct llist_node_st *cur;
for(cur=ptr->head.next;cur != &ptr->head;cur=cur->next)
{
op(cur->data);
}
}
- llist.h文件内容
#ifndef LLIST_H__
#define LLIST_H__
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
typedef void LLIST;
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);
int llist_insert(LLIST *,const void *data,int mode);
int llist_delete(LLIST *,const void *key,llist_cmp *);
void *llist_find(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp*,void *data);
void llist_show(LLIST *,llist_op *);
#endif
- main.c文件内容:
#include <stdio.h>
#include <stdlib.h>
#include "llist.h"
#define NAMESIZE 32
struct score_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};
void print_s(const void *record)
{
const struct score_st *r=record;
printf("%d %s %d %d \n",r->id,r->name,r->math,r->chinese);
}
static int id_cmp(const void *key,const void *record)
{
const int *k=key;
const struct score_st *r=record;
return (*k-r->id);
}
int main()
{
int i;
int ret;
LLIST *handler;
struct score_st tmp;
handler=llist_create(sizeof(struct score_st));
/*if err*/
for(i=0;i<7;i++)
{
tmp.id=i;
snprintf(tmp.name,NAMESIZE,"std%d",i);
tmp.math=rand()%100;
tmp.chinese=rand()%100;
ret=llist_insert(handler,&tmp,LLIST_BACKWARD);
if(ret)
{
exit(1);
}
}
llist_show(handler,print_s);
printf("\n \n");
int id=3;
struct score_st *data;
llist_delete(handler,&id,id_cmp);
llist_show(handler,print_s);
data=llist_find(handler,&id,id_cmp);
if(data==NULL)
{
printf("sorry ,can not find.\n");
}
else
{
print_s(data);
}
llist_destroy(handler);
exit(0);
}
其他文件内容不变。
内核双向链表的赏析:
根据内核的代码写双向循环链表
- list.h文件内容:
#ifndef LINUX_LIST_H__
#define LINUX_LIST_H__
struct list_head
{
struct list_head *prev;
struct list_head *next;
};
#define LIST_HEAD_INIT(name) {&(name),&(name)}
#define LIST_HEAD(name) struct list_head name=LIST_HEAD_INIT(name)
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/*
ptr->cur;
type->struct score_st
member->node
*/
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#endif
- main.c文件内容:
#include <stdio.h>
#include <stdlib.h>
#define NAMESIZE 32
#include "list.h"
struct score_st
{
int id;
char name[NAMESIZE];
struct list_head node;
int math;
int chinese;
};
static void print_s(struct score_st *d)
{
printf("%d %s %d %d \n",d->id,d->name,d->math,d->chinese);
}
int main()
{
struct score_st *datap;
struct list_head *cur;
LIST_HEAD(head);
int i;
for(i=0;i<7;i++)
{
datap=malloc(sizeof(*datap));
if(datap == NULL)
exit(1);
datap->id=i;
snprintf(datap->name,NAMESIZE,"stu%d",i);
datap->math=rand()%100;
datap->chinese=rand()%100;
list_add(&datap->node,&head);
}
list_for_each(cur,&head)
{
datap=list_entry(cur,struct score_st,node);
print_s(datap);
}
//find
list_for_each(cur,&head)
{
datap=list_entry(cur,struct score_st,node);
if(datap->id == 5)
break;
}
if(cur==&head)
printf("Can not find the id\n");
else
print_s(datap);
exit(0);
}
运行结果: