通用数据结构之线性表基本操作

// 完成了单链表的所有操作: 增,删,前插,后插,回调遍历,复制,销毁,反转,排序
// 对于队列和栈就简单了,稍稍修改即可

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

#define list_create(A) list_init(A)

typedef struct node{
    struct node *next;
    void *data;
}node;

typedef struct {
    node *head;
}list_t;  // 单链表

typedef struct {
    node *head;
    node *tail;
}queue_t; // 队列

typedef struct {
    node *top;
}stack_t; // 栈

inline static node *makenode(void *data);
inline static void freenode(node *p);
void list_init(list_t *list);
size_t list_length(list_t *list);
void list_destroy(list_t *list);
node *list_getnode(list_t *list, int id);
void list_add(list_t *list, void *data);
void list_insertBack(list_t *list, node *n, void *data);
void list_insertFront(list_t *list, node *n, void *data);
void list_del(list_t *list, node *del);
void list_traverse(list_t *list, void(*visit)(void *));
void list_reverse(list_t *list);
void list_sort(list_t *list, int(*cmpar)(const void *, const void *));
void list_copy(list_t *dest, list_t *src);
void list_add2(list_t *list, void *data);
void list_del2(list_t *list, node *del);
void list_insertFront2(list_t *list, node *n, void *data);
void disp(int n);
int cmpar(const void *data1, const void *data2);
int main(int argc, char **argv);

inline static node *makenode(void *data)
{
    node *p;
    if( (p = malloc(sizeof(*p))) == NULL){
        perror("malloc");
        exit(1);
    }

    p->next = NULL;
    p->data = data;
    return p;
}

inline static void freenode(node *p)
{
    free(p);
}


// 初始化
void list_init(list_t *list)
{
    list->head = NULL;    
}
size_t list_length(list_t *list)
{
    node *p;
    int len;
    for(p = list->head, len = 0; p; p = p->next, len++)
        ;
    return len;
}
// 销毁一个链表
void list_destroy(list_t *list)
{
    node *p;
    for(p = list->head; p; p = p->next)
        list_del(list, p);
}

// 按顺序编号获取某个节点
node *list_getnode(list_t *list, int id)
{
    node *p;
    int n;
    for(p = list->head, n = 0; p; p = p->next, n++)
        if(n == id)
            return p;
    return NULL;  // 最后1个节点的后继或没有找到
}

// 添加
void list_add(list_t *list, void *data)
{
    if(list->head == NULL){ // 特殊情况:头结点判断
        list->head = makenode(data);
    }else{
        node *p = list->head;
        while(p->next) // 获取最后一个节点
            p = p->next;
        p->next = makenode(data);
    }
}
// 后插
void list_insertBack(list_t *list, node *n, void *data)
{
    // assert(n);
    if(n == NULL)
        return;
    node *ins = makenode(data);
    ins->next = n->next;
    n->next = ins;
}

// 前插
void list_insertFront(list_t *list, node *n, void *data)
{
    node *ins = makenode(data);
    ins->next = n;
    if(n == list->head){ // 特殊情况:头结点判断
        list->head = ins;
    }else{ // 获取n的前驱
        node *p;
        for(p = list->head; p; p = p->next)
            if(p->next == n){ 
                p->next = ins;
                return;
            }
    }
}

// 删除一个节点
void list_del(list_t *list, node *del)
{
    if(del == NULL)
        return;
    node *p;
    if(list->head == del){// 特殊情况:头结点判断
        list->head = list->head->next;
    }else{
        for(p = list->head; p; p = p->next)
            if(p->next == del){
                p->next = del->next;
                freenode(del);
        }       
    }
}

// 遍历
void list_traverse(list_t *list, void(*visit)(void *))
{
    node *p;
    if(list->head == NULL){
        puts("empty !");
        return;
    }
    for(p = list->head; p; p = p->next)
        visit(p->data);
    puts("");

}

// 反转
void list_reverse(list_t *list)
{
    node *tmp, *p, *head = NULL;
    for(p = list->head; p; p = tmp){
        tmp = p->next; // 暂存p的后继节点
        p->next = head, head = p; // 将p插到head前
    }
    list->head = head;
}

// 排序
void list_sort(list_t *list, int(*cmpar)(const void *, const void *))
{
    size_t len;
    void **parr;
    node *p;
    int i;

    len = list_length(list);
    parr = malloc(sizeof(void *)*len);

    for(p = list->head, i = 0; p; p = p->next, i++)
        parr[i] = p->data;
    qsort(parr, len, sizeof(void *), cmpar);
    
    for(p = list->head, i = 0; p; p = p->next, i++)
        p->data = parr[i];

    free(parr);

}

// 复制一个链表
void list_copy(list_t *dest, list_t *src)
{
    node *p;
    for(p = src->head; p; p = p->next)
        list_add(dest, p->data);
}

// -----------------------------------------------------
void list_add2(list_t *list, void *data)
{
    node **p;
    for(p = &list->head; *p; p = &(*p)->next)
        ; // 获取最后一个节点地址
    *p = makenode(data);
}

void list_del2(list_t *list, node *del)
{
    node **p;
    for(p = &(list->head); *p; p = &(*p)->next){
        if(*p == del){
            *p = del->next;
            freenode(del);
            if(*p == NULL)
                return;
        }
    }
}

void list_insertFront2(list_t *list, node *n, void *data)
{
    node **p;
    node *ins = makenode(data);
    ins->next = n;
    for(p = &list->head; *p; p = &(*p)->next)
        if(*p == n){
            *p = ins;
            return;
        }
    *p = ins; // n == NULL
}



// -------------------------------------------------

void disp(int n)
{
    printf("%c_",n);
}

int cmpar(const void *data1, const void *data2)
{
    return *(int *)data1 - *(int *)data2;
}

void(*show)(void *) = (void(*)(void *))disp;





int main(int argc, char **argv)
{

    list_t list;
    list_init(&list);
    
    list_insertFront(&list, list.head, (void *)'2');
    list_insertFront(&list, list.head, (void *)'5');
    list_insertFront(&list, list.head, (void *)'c');
    list_insertFront(&list, list.head, (void *)'d');
    list_traverse(&list, show);
    list_traverse(&list, show);  

    node *p = list_getnode(&list, 2); // p==NULL
    list_insertBack(&list, p, (void *)'X');

    list_traverse(&list, show);   
    list_insertFront2(&list, p, (void *)'x');
    list_traverse(&list, show);   

    p = list_getnode(&list, 2);
    list_del(&list, p);
    list_traverse(&list, show);  

    list_add2(&list, (void *)'3');
    list_add2(&list, (void *)'1');
    list_traverse(&list, show);   

    list_reverse(&list);
    list_traverse(&list, show);  

    list_t list2;
    list_init(&list2);
    list_copy(&list2, &list);
    list_traverse(&list2, show);  

    list_destroy(&list2);
    list_traverse(&list2, show); // empty

    list_sort(&list, cmpar);
    list_traverse(&list, show);
    return 0;
}

  

posted @ 2012-10-11 00:02  庄庄庄  阅读(208)  评论(0编辑  收藏  举报