简单通用链表 demo

Posted on Mar 5, 2023
tl;dr: 自己实现的通用链表 demo

以下是参考Linux链表实现的简易通用链表,目前水平有限,只能理解大概思想,做一个玩具 demo:

后续继续学习后再做补充。

klist.h

#ifndef _KLINK_LIST
#define _KLINK_LIST
/****************************************************************************
* @file        : incl/klinklist.h
* @brief       : 通用链表
* @author      : shachi
* @email       : shachi1758@outlook.com
* @details     :
* @version     : 0.1.0
* @history     :
*      2023-03-02 16:29:52 创建文件
*      2023-03-05 15:11:19 实现初始化、头插法。
****************************************************************************/

#include <stdint.h>
#include <stddef.h>

/**
 * @brief 通用头节点
 */
struct klist_head{
    struct klist_head *prev;
    struct klist_head *next;
};

/**
 * @brief: 通用链表初始化
 * @param1: l,链表头
 *
 * 前驱和后继都指向自己。
 *
 */
inline void klist_init(struct klist_head *head)
{
    head->next = head;
    head->prev = head;
}

/**
 * @brief: 头插法插入节点
 * @param1: new,要插入的节点
 * @param2: l,要插入的链表
 *
 * @return: -1,插入失败
 *           0,插入成功
 *
 */
int32_t klist_add(struct klist_head *new,struct klist_head *head);

/**
 * @brief: 删除节点。
 * @param1: head,待删除的节点。
 *
 * 删除链表上的节点,只是从链表中删除,不会释放空间。
 *
 * @return: -1 失败
 *           0 成功
 */
int32_t klist_del(struct klist_head *head);

#endif //  _KLINK_LIST

klist.c

/****************************************************************************
* @file        : ./src/klink_list.c
* @brief       :
* @author      : shachi
* @email       : shachi1758@outlook.com
* @details     :
* @version     : 0.1.0
* @history     :
*      2023-03-05 14:53:47 创建文件
*      2023-03-05 15:11:19 实现初始化、头插法。
****************************************************************************/

#include "klinklist.h"


int32_t klist_add(struct klist_head *new, struct klist_head *head)
{
    if(!head || !new) return -1;
    // 原来的第一个节点前驱指针指向新节点。
    head->next->prev = new;
    // 新节点的后继指针指向原来的第一个节点。
    new->next = head->next;
    // 头节点的后继指针指向新节点。
    head->next = new;
    // 新节点的前驱指针指向头节点。
    new->prev = head;
    return 0;
}


int32_t klist_del(struct klist_head *head)
{
    if(!head) return -1;
    // 后继节点前驱指针指向待删除节点前一个
    head->next->prev = head->prev;
    // 前驱节点后继指针指向待删除节点后一个
    head->prev->next = head->next;
    // 被删除节点的前驱后继指向 NULL
    head->prev=NULL;
    head->next=NULL;
    return 0;
}

main.c

/****************************************************************************
* @file        : ./src/main.c
* @brief       :
* @author      : shachi
* @email       : shachi1758@outlook.com
* @details     :
* @version     : 0.1.0
* @history     :
*      2023-03-05 14:17:41 创建文件
****************************************************************************/

#include <malloc.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "klinklist.h"
#include "klogger.h"

struct student{
    struct klist_head head;
    int32_t id;
    int32_t age;
};

int main(int argc, const char* argv[])
{
    struct student *st_head = (struct student *) malloc (sizeof(struct student));
    // 初始化学生信息链表
    klist_init((struct klist_head *)st_head);

    // 插入六个学生信息。
    for (size_t i = 0; i < 6; ++ i){
        struct student *ptr = (struct student*) malloc(sizeof(struct student));
        ptr->id = i;
        ptr->age = i + 15;
        klist_add((struct klist_head *) ptr,(struct klist_head *) st_head);
    }

    // 打印学生信息
    struct klist_head *ptr = st_head->head.next;
    while(ptr->next != st_head->head.next) {
        printf("id:%d,age:%d\n",((struct student *)ptr)->id,((struct student *)ptr)->age);
        ptr = ptr->next;
    }

    // 删除一些学生信息。
    struct klist_head *ptr2 = st_head->head.next;
    struct student *ptr_del;
    while(ptr2->next != st_head->head.next){
        ptr_del = (struct student *)ptr2;
        if(ptr_del->age == 16) {
            printf("id:%d,age:%d is deleted.\n",ptr_del->id,ptr_del->age);
            struct klist_head *tmp = ptr2->next;
            klist_del(ptr2);
            // 释放空间。
            free(ptr2);
            ptr2 = tmp;
            continue;
        }
        ptr2 = ptr2->next;
    }

    // 打印删除后的链表。
    struct klist_head *pt = st_head->head.next;
    while(pt->next != st_head->head.next) {
        printf("id:%d,age:%d\n",((struct student *)pt)->id,((struct student *)pt)->age);
        pt = pt->next;
    }

    return 0;
}

参考:


留言或评论请使用 Github Issues