双向循环链表

双向循环链表

在这里插入图片描述

带头结点的双向循环链表

插入的操作:
在这里插入图片描述

基础代码:

  • 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);
}

运行结果:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值