通用链表代码1

双链表和表头的好处,链表永远不为空,构造链表尽量用这种方法。


include <stdio.h>
#include <stdlib.h>

typedef int (*fp_node_proc)(void* datap, void *cookie);
typedef int (*fp_node_cmp)(const void*, const void*);
 
struct node_st {
    void *datap;
    struct node_st *next, *prev;
};
 
struct llist_st {
    struct node_st head;
    int elmsize;
    int elmnr;
};

void* llist_new(int elmsize)
{
    struct llist_st *newlist;
    
    newlist = (struct llist_st *)malloc(sizeof(struct llist_st));
    if (newlist == NULL) {
        return NULL;
    }

    newlist->head.datap = NULL;
    newlist->head.next = &newlist->head;
    newlist->head.prev = &newlist->head;
    newlist->elmsize = elmsize;

    return (void*)newlist;
}

int llist_destroy(void *llist)
{
    struct llist_st *me = llist;
    struct node_st *curr, *saved;

    if (NULL == llist) return -1;
    for ( curr = me->head.next ; curr != &me->head; curr = saved ) {
        saved = curr->next;
        free(curr->datap);
        free(curr);
    }

    free(me);
    return 0;
}

int llist_node_append(void *llist, const void *datap)
{
    struct llist_st *me = llist;
    struct node_st *newnodep;

    newnodep = (struct node_st *)malloc(sizeof(struct node_st));
    if (newnodep == NULL) {
        return -1;
    }
    
    newnodep->datap = malloc(me->elmsize);
    if (newnodep->datap == NULL) {
        free(newnodep);
        return -1;
    }

    // insert as last
    memcpy(newnodep->datap, datap, me->elmsize);
    newnodep->prev = me->head.prev;
    newnodep->next = &me->head;
    me->head.prev->next = newnodep;
    me->head.prev = newnodep;

    return 0;
}

int llist_node_insert(void* llist, const void* datap, fp_node_cmp comp)
{
    struct llist_st *me = llist;
    struct node_st *curr = NULL;
    struct node_st *newnodep;

    if (NULL == llist) return -1;
    if (NULL == comp) return -1;

    newnodep = (struct node_st *)malloc(sizeof(struct node_st));
    if (newnodep == NULL) {
        return -1;
    }
    newnodep->datap = malloc(me->elmsize);
    if (newnodep->datap == NULL) {
        free(newnodep);
        return -1;
    }
    memcpy(newnodep->datap, datap, me->elmsize);

    for ( curr = me->head.next; curr != &me->head; curr = curr->next ) {
        if ( comp(curr->datap, datap) > 0 ) {
            // insert before curr, maybe as first
            newnodep->next = curr;
            newnodep->prev = curr->prev;
            curr->prev->next = newnodep;
            curr->prev = newnodep;
            return 0;
        }
    }

    // insert as last
    newnodep->next = &me->head;
    newnodep->prev = me->head.prev;
    me->head.prev->next = newnodep;
    me->head.prev = newnodep;
    
    return 0;
}

void *llist_node_delete(void* llist, const void *key, fp_node_cmp comp)
{
    struct llist_st *me = llist;
    struct node_st *curr = NULL;

    if (NULL == llist) return NULL;
    if (NULL == comp) return NULL;

    for ( curr = me->head.next; curr != &me->head; curr = curr->next) {
        if ( comp(curr->datap, key) == 0 ) {
            curr->prev->next = curr->next;
            curr->next->prev = curr->prev;
            return curr->datap;
        }
    }
    
    return NULL;
}

// if proc return !0, then break the travel
int llist_travel(void* llist, fp_node_proc proc, void *cookie)
{
    struct llist_st *me = (struct llist_st *)llist;
    struct node_st *curr;

    if (NULL == llist) return -1;
    if (NULL == proc) return -1;
    
    for ( curr = me->head.next; curr != &me->head; curr = curr->next ) {
        if ( 0 != proc(curr->datap, cookie) ) {
            break;
        }
    }
    
    return 0;
}

void* llist_node_find(void *llist, fp_node_cmp comp, const void *key)
{
    struct llist_st *me = llist;
    struct node_st *curr;

    if (NULL == llist) return NULL;
    if (NULL == comp) return NULL;

    for ( curr = me->head.next; curr != &me->head; curr = curr->next ) {
        if ( comp(curr->datap, key) == 0 ) {
            return curr->datap;
        }
    }
    
    return NULL;
}

int llist_sort(void* llist, fp_node_cmp comp)
{
    struct llist_st *me = llist;
    struct node_st *curr;
    struct node_st *ptr, *saved;
    struct node_st temp_head;

    if (NULL == llist) return -1;
    if (NULL == comp) return -1;

    temp_head.prev = &temp_head;
    temp_head.next = &temp_head;
    
    for (curr = me->head.next; curr != &me->head; curr = saved) {
        saved = curr->next;
        for (ptr = temp_head.next; ptr != &temp_head; ptr = ptr->next) {
            if ( comp(ptr->datap, curr->datap) > 0 ) {
                // insert before curr, maybe as first
                curr->next = ptr;
                curr->prev = ptr->prev;
                ptr->prev->next = curr;
                ptr->prev = curr;
                break;
            }
        }

        // insert as last
        if ( ptr == &temp_head ){
            curr->next = &temp_head;
            curr->prev = temp_head.prev;
            temp_head.prev->next = curr;
            temp_head.prev = curr;
        }
    }

    me->head.next = temp_head.next;
    me->head.prev = temp_head.prev;
    temp_head.next->prev = &me->head;
    temp_head.prev->next = &me->head;
        
    return 0;
}

测试代码:

typedef struct tagUSER_DATA_ST
{
    int id;
    int param;
}USER_DATA_ST;

int node_print(void* datap, void *cookie)
{
    USER_DATA_ST *ptr = (USER_DATA_ST *)datap;
    printf("%d(%d) ", ptr->id, ptr->param);
    return 0;
}

int node_cmp(const void* datap, const void* key)
{
    USER_DATA_ST *ptr1 = (USER_DATA_ST *)datap;
    USER_DATA_ST *ptr2 = (USER_DATA_ST *)key;
    return (ptr1->id - ptr2->id);
}

int main()
{
    int i;
    USER_DATA_ST temp;
    USER_DATA_ST *ptr;
    USER_DATA_ST *my_llist = llist_new(sizeof(USER_DATA_ST));

    printf("\r\n init  : ");
    srand(0);
    for(i = 10; i > 0; i--) {
        temp.id = i;
        temp.param = rand()%100;
        llist_node_append(my_llist, &temp);
    }
    llist_travel(my_llist, node_print, NULL);

    printf("\r\n delete: ");
    temp.id = 0; llist_node_delete(my_llist, &temp, node_cmp);
    temp.id = 3; llist_node_delete(my_llist, &temp, node_cmp);
    temp.id = 5; llist_node_delete(my_llist, &temp, node_cmp);
    temp.id = 8; llist_node_delete(my_llist, &temp, node_cmp);
    llist_travel(my_llist, node_print, NULL);

    printf("\r\n find  : ");
    temp.id = 3; ptr = llist_node_find(my_llist, node_cmp, &temp);
    if(NULL != ptr) printf("\r\n find error");
    temp.id = 4; ptr = llist_node_find(my_llist, node_cmp, &temp);
    if(NULL == ptr) printf("\r\n find error");
    node_print(ptr, NULL);

    printf("\r\n sort  : ");
    llist_sort(my_llist, node_cmp);
    llist_travel(my_llist, node_print, NULL);

    printf("\r\n insert: ");
    temp.id = 0; temp.param = 111;
    llist_node_insert(my_llist, &temp, node_cmp);
    temp.id = 5; temp.param = 222;
    llist_node_append(my_llist, &temp);
    temp.id = 20; temp.param = 333;
    llist_node_insert(my_llist, &temp, node_cmp);
    llist_travel(my_llist, node_print, NULL);

    printf("\r\n sort  : ");
    llist_sort(my_llist, node_cmp);
    llist_travel(my_llist, node_print, NULL);

    printf("\r\n destroy: ");
    llist_destroy(my_llist);
    
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值