C-单链表的实现

本文将介绍使用C中关键字struct 定义结构体实现单链表。

在C语言中,结构体的自引用只能通过指针来实现,因为在系统中指针的大小是固定(32位系统时大小是4字节,64位系统时大小是8字节)。

结构体自引用实现方式

有2种实现方式,

方式一:

typedef struct tagNode
{
    char *pItem;
    struct tagNode *next;
} *pNode; // 注意结构体的结尾一定得有分号

方式二:

// typedef 一定要定义在struct之前
typedef struct tagNode *pNode; 
struct tageNode
{
    char *pItem;
    pNode next;
};

链表定义

定义链表和相关操作

// 定义一个用显示数据的函数指针
typedef void (*DISPLAY)(void*);
// 定义一个用于比较数据大小的函数指针
typedef int (*COMPARE)(void*, void*);

// 节点定义
typedef struct _node
{
    void *data; // 节点数据
    struct _node *next; // 下一个节点
} *pNode;

// 链表定义
typedef struct _linkedlist
{
    pNode *head;
    pNode *tail;
    pNode *current;
} LinkedList;

// 初始化链表
void init_linkedlist(LinkedList *list)
{
    list->head = NULL;
    list->tail = NULL;
    list->current = NULL;
}

// 向链表头添加数据节点
void addHead(LinkedList *list, void *data)
{
    pNode node = (pNode) 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)
{
    pNode node = (pNode) malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    if (list->head == NULL) {
        list->head = node;
    } else {
        list->tail->next = node;
    }
    list->tail = node;
}

// 获取指定的节点信息
pNode getNode(LinkedList *list, COMPARE compare, void *data) 
{
    pNode node = list->head;
    while (node != NULL) {
        if (compare(node->data, data)) {
            return node;
        }
        node = node->next;
    }
    return NULL;
}
// 删除指定的节点
void deleteNode(LinkedList *list, pNode node)
{
    if (node == list->head)
    {
        if (list->head->next == NULL) {
            list->head = list->tail = NULL;
        } else {
            list->head = list->head->next;
        }
    } else {
        pNode tmp = list->head;
        while (tmp != NULL && tmp->next != node)
        {
            tmp = tmp->next;
        }
        if (tmp != NULL) {
            tmp->next = node->next;
        }
    }
    
    free(node);
}
// 展示数据
void displayList(LinkedList *list, DISPLAY display)
{
    printf("\nLinkedList shown:\n");
    pNode node = list->head;
    while (node != NULL) {
        display(node->data);
        node = node->next;
    }
}

// 比较函数
int compareInt(int *e1, int *e2)
{
    return *e1 == *e2;
}
// 显示数据
void displayIntVal(int *e)
{
    printf("%d\n", *e);
}

使用示例

1.从链表头部开始添加数据

    LinkedList linkedList;
    // 初始化
    init_linkedlist(&linkedList);
    int a = 20;
    int b = 30;
    int c = 40;
    int *ptr_1 = &a;
    int *ptr_2 = &b;
    int *ptr_3 = &c;

    addHead(&linkedList, ptr_1);
    addHead(&linkedList, ptr_2);
    addHead(&linkedList, ptr_3);

    displayList(&linkedList, (DISPLAY)displayIntVal);

打印结果:

LinkedList shown:
40
30
20

2.从链表尾部添加数据

    LinkedList linkedList;
    // 初始化
    init_linkedlist(&linkedList);
    int a = 20;
    int b = 30;
    int c = 40;
    int *ptr_1 = &a;
    int *ptr_2 = &b;
    int *ptr_3 = &c;

    addTail(&linkedList, ptr_1);
    addTail(&linkedList, ptr_2);
    addTail(&linkedList, ptr_3);

    displayList(&linkedList, (DISPLAY)displayIntVal);

打印结果:

LinkedList shown:
20
30
40

3.获取指定的节点

    LinkedList linkedList;
    // 初始化
    init_linkedlist(&linkedList);
    int a = 20;
    int b = 30;
    int c = 40;
    int *ptr_1 = &a;
    int *ptr_2 = &b;
    int *ptr_3 = &c;

    addTail(&linkedList, ptr_1);
    addTail(&linkedList, ptr_2);
    addTail(&linkedList, ptr_3);

    pNode node = getNode(&linkedList, (COMPARE) compareInt, ptr_2);
    printf("node val is %d\n", *((int *)node->data));

打印结果:

node val is 30

4.删除指定的节点

    LinkedList linkedList;
    // 初始化
    init_linkedlist(&linkedList);
    int a = 20;
    int b = 30;
    int c = 40;
    int *ptr_1 = &a;
    int *ptr_2 = &b;
    int *ptr_3 = &c;

    addTail(&linkedList, ptr_1);
    addTail(&linkedList, ptr_2);
    addTail(&linkedList, ptr_3);

    pNode node = getNode(&linkedList, (COMPARE) compareInt, ptr_2);
    printf("node val is %d\n", *((int *)node->data));

    deleteNode(&linkedList, node);
    displayList(&linkedList, (DISPLAY)displayIntVal);

打印结果:

node val is 30

LinkedList shown:
20
40


以上就是全部的内容,如有错误,欢迎留言交流或者关注公众号交流。