美文网首页
[C指针]指针与结构体:完整源码 C语言 实现 单链表

[C指针]指针与结构体:完整源码 C语言 实现 单链表

作者: AkuRinbu | 来源:发表于2019-04-17 14:38 被阅读0次

    学习笔记

    《深入理解C指针》
    http://www.ituring.com.cn/book/1147
    第6章 指针与结构体

    本文结构

    • 函数模板:自定义的一个雇员结构体
    • 单链表实现:头部增加结点addHead、尾部增加结点addTail、获取指定结点getNode、删除指定结点deleteN、比较函数(函数指针)、显示函数(函数指针)
    • 完整源码:C语言 实现 单链表

    函数模板

    - 一个雇员结构体
    
    typedef struct _employee{
        char name[32];
        unsigned char age;
    } Employee;  
    
    - 基于雇员名字的比较函数
    
    int compareEmployee(Employee *e1, Employee *e2) {
        return strcmp(e1->name, e2->name);
    }
    
    - 显示函数
    
    void displayEmployee(Employee* employee) {
        printf("%s\t%d\n", employee->name, employee->age);
    }
    
    - 两个函数指针
    
    typedef void(*DISPLAY)(void*);
    typedef int(*COMPARE)(void*, void*);
    

    DISPLAY函数指针表示一个接受void*参数并返回void的函数,目的是显示数据
    COMPARE函数比较两个指针引用的数据,它的返回值是0-11

    单链表

    结点的定义

    typedef struct _node {
        void *data;
        struct _node *next;
    } Node;
    

    void * data 意味着可以是任意的指针,即可以是普通的数据类型指针(比如int *),也可以是结构体指针(比如Employee *

    • 结点结构体定义 void * data;
    • 函数的形式参数 void addHead(LinkedList *list, void* data) {}
    • 实际代码传入的参数,是一个结构体指针
      Employee *samuel = (Employee*) malloc(sizeof(Employee));
      addHead(&linkedList, samuel);
    void * data

    比较函数的函数指针

    比较函数的函数指针
    • 只要传入参数是两个void *,就是COMPARE类型的函数
    typedef int(*COMPARE)(void*, void*);
    
    • 函数类型是COMPARE,函数名是compare
    Node *getNode(LinkedList *list, 
              COMPARE compare , void* data) {
     . . .
    
            if (compare(node->data, data) == 0) { }
     
     . . .
    }
    

    compare函数说明了如何在运行时用函数指针来决定用哪个函数执行比较操作,这样会给链表的实现增加可观的灵活性,因为我们不需要在getNode函数中硬编码比较函数的名字。

    显示函数的函数指针

    显示函数 的 调用关系 示意图
    • 定义函数类型 typedef void(*DISPLAY)(void*);
      只要输入参数是 void* 并且返回 void 的函数就可以被叫做 DISPLAY类型

    • 传入函数指针,调用时直接写 display(. . .);

    void displayLinkedList( LinkedList *list, 
          DISPLAY display) {
    . . .
            display(current->data);
    . . .
    }
    
    • 具体地实现一个以Employee *作为输入参数并且返回 void的函数
    void displayEmployee ( Employee* employee ) {
        printf("%s\t%d\n", employee->name, employee->age);
    }
    
    • 把全部的东西整合起来,在main函数里面定义一切
      displayLinkedList( &linkedList, (DISPLAY)displayEmployee );

    运行结果

    运行结果

    完整源码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef void(*DISPLAY)(void*);
    typedef int(*COMPARE)(void*, void*);
    
    typedef struct _employee{
        char name[32];
        unsigned char age;
    } Employee;  
    
    int compareEmployee(Employee *e1, Employee *e2) {
        return strcmp(e1->name, e2->name);
    }
    
    void displayEmployee(Employee* employee) {
        printf("%s\t%d\n", employee->name, employee->age);
    }
    
    typedef struct _node {
        void *data;
        struct _node *next;
    } Node;
    
    typedef struct _linkedList {
        Node *head;
        Node *tail;
        Node *current;
    } LinkedList;
    
    void initializeList(LinkedList *list) {
        list->head = NULL;
        list->tail = NULL;
        list->current = NULL;
    }
    
    void addHead(LinkedList *list, void* data) {
        Node *node = (Node*) malloc(sizeof(Node));
        node->data = data;
        if (list->head == NULL) {
            list->tail = node;
            node->next = NULL;
        } else {
            node->next = list->head;
        }
        list->head = node;
    }
    
    void addTail(LinkedList *list, void* data) {
        Node *node = (Node*) malloc(sizeof(Node));
        node->data = data;
        node->next = NULL;
        if (list->head == NULL) {
            list->head = node;
        } else {
            list->tail->next = node;
        }
        list->tail = node;
    }
    
    Node *getNode(LinkedList *list, COMPARE compare , void* data) {
        Node *node = list->head;
        while (node != NULL) {
            if (compare(node->data, data) == 0) {
                return node;
            }
            node = node->next;
        }
        return NULL;
    }
    
    void deleteN(LinkedList *list, Node *node) {
        if (node == list->head) {
            if (list->head->next == NULL) {
                list->head = list->tail = NULL;
            } else {
                list->head = list->head->next;
            }
        } else {
            Node *tmp = list->head;
            while (tmp != NULL && tmp->next != node) {
                tmp = tmp->next;
            }
            if (tmp != NULL) {
                tmp->next = node->next;
            }
        }
        free(node);
    }
    
    void displayLinkedList(LinkedList *list, DISPLAY display) {
        printf("\nLinked List\n");
        Node *current = list->head;
        while (current != NULL) {
            display(current->data);
            current = current->next;
        }
    }
    
    int main()
    {
        LinkedList linkedList;
    
        Employee *samuel = (Employee*) malloc(sizeof(Employee));
        strcpy(samuel->name, "Samuel");
        samuel->age = 32;
        
        Employee *sally = (Employee*) malloc(sizeof(Employee));
        strcpy(sally->name, "Sally");
        sally->age = 28;
        
        Employee *susan = (Employee*) malloc(sizeof(Employee));
        strcpy(susan->name, "Susan");
        susan->age = 45;
        
        initializeList(&linkedList);
        
        addHead(&linkedList, samuel);
        addHead(&linkedList, sally);
        addHead(&linkedList, susan);
        
        Node *node = getNode(&linkedList, 
                (int (*)(void*, void*))compareEmployee , sally);
        
        displayLinkedList(&linkedList, (DISPLAY)displayEmployee);
        
        printf("Message:Delete Sally.\n");
        deleteN(&linkedList, node);
        
        displayLinkedList(&linkedList, (DISPLAY)displayEmployee);
    }
    

    相关文章

      网友评论

          本文标题:[C指针]指针与结构体:完整源码 C语言 实现 单链表

          本文链接:https://www.haomeiwen.com/subject/jeobwqtx.html