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

学习笔记

《深入理解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);
[C指针]指针与结构体:完整源码 C语言 实现 单链表_第1张图片
void * data

比较函数的函数指针

[C指针]指针与结构体:完整源码 C语言 实现 单链表_第2张图片
比较函数的函数指针
  • 只要传入参数是两个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函数中硬编码比较函数的名字。

显示函数的函数指针

[C指针]指针与结构体:完整源码 C语言 实现 单链表_第3张图片
显示函数 的 调用关系 示意图
  • 定义函数类型 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 );

运行结果

[C指针]指针与结构体:完整源码 C语言 实现 单链表_第4张图片
运行结果

完整源码

#include 
#include 
#include 

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语言 实现 单链表)