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


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

      

  • 相关阅读:
    C#:基于WMI查询USB设备信息 及 Android设备厂商VID列表
    C#中 @ 的3种用途
    有关于 使用 命名管道 进行网络 进程间通信 的资料收集
    MySql LAST_INSERT_ID 【插入多条数据时】
    两个“不合理继承 ”的判定标识
    MYSQL 函数 字符串到整数
    Spring MVC 对于@ModelAttribute 、@SessionAttributes 的详细处理流程
    重构,拥有多个构造函数(重载)的类
    vue二级联动select
    gulp.dest用法详解
  • 原文地址:https://www.cnblogs.com/mathzzz/p/2719225.html
Copyright © 2020-2023  润新知