C 单链表

表的结构

#define MAXSIZE 20
#define listData uint32_t

typedef struct list_t {
    listData data;
    struct list_t* next;
} list_t;

常用方法

  • list_init:初始化,建立一个空表
  • list_uninit:free整个链表
  • list_clear:清空当前表
  • list_insert_head:从表头插入数据
  • list_insert_tail:从表尾部插入数据
  • list_insert:插入一个数据,index = 2,则会替换掉原来的2,原来的2变成3
  • list_delete:删除指定位置的节点
  • list_merge:合并2个表
  • list_reverse:逆序
  • list_display:打印表数据

实现代码

list.h

#ifndef __LIST_H__
#define __LIST_H__

#include <stdint.h>
#include <stdbool.h>

#define OK 0x0000
#define ERROR 0xFFFF

#define MAXSIZE 20
#define listData uint32_t

typedef struct list_t {
    listData data;
    struct list_t* next;
} list_t;

list_t* list_init(); /* 构建头指针 */
void list_uninit(list_t** s_p_list); /* free整个链表 */
void list_clear(list_t* p_list);
uint32_t list_insert_head(list_t* p_list, listData data); /* 从表头插入数据 */
uint32_t list_insert_tail(list_t* p_list, listData data); /* 从表尾部插入数据 */
uint32_t list_insert(list_t* p_list, uint32_t index, listData data); /* index = 2,则会替换掉原来的2,原来的2变成3 */
uint32_t list_delete(list_t* p_list, uint32_t index); /* 删除指定位置的节点 */
uint32_t list_merge(list_t* p_list, uint32_t index, list_t* p_list_2); /* 在list_1指定节点之后拼接上List_2 */
void list_reverse(list_t* p_list);
void list_display(list_t* p_list); /* 遍历链表 */

#endif // __LIST_H__

list.c

#include "list.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

list_t* list_init() {
    list_t* p_list = (list_t*)malloc(sizeof(list_t));
    if (p_list != NULL) {
        memset(&p_list->data, 0x00, sizeof(listData));
        p_list->next = NULL;
    }
    return p_list; /* 返回头指针 */
}

void list_uninit(list_t** s_p_list) {
    if (s_p_list == NULL || *s_p_list == NULL) {
        return;
    }

    /* 清空链表所有数据 */
    list_t* p = (*s_p_list)->next;
    list_t* q = NULL;

    while (p != NULL) {
        q = p->next;
        free(p);
        p = q;
    }

    /* free掉头指针 */
    free(*s_p_list);
    *s_p_list = NULL;
}

void list_clear(list_t* p_list) {
    list_t* p = p_list->next; /* 指向第一个节点 */
    list_t* q = NULL; /* 中转 */

    /* p != NULL的时候,表示一直还有后续的节点存在 */
    while (p != NULL) {
        q = p->next; /* q临时记录一下,p的下一个节点的位置 */
        free(p); /* 释放当前节点p */
        p = q; /* p继续指向自己的下一个节点 */
    }
    p_list->next = NULL;
    /* 清空,没有删除掉头指针的,还可以继续利用p_list来操作链表 */
}

uint32_t list_insert_head(list_t* p_list, listData data) {
    /* 创建一个节点,将数据放置进去 */
    list_t* newNode = (list_t*)malloc(sizeof(list_t));
    if (newNode == NULL) {
        return ERROR;
    }
    memcpy(&newNode->data, &data, sizeof(listData));
    newNode->next = NULL;

    /* 插入为第一个节点 */
    newNode->next = p_list->next;
    p_list->next = newNode;
    return OK;
}

uint32_t list_insert_tail(list_t* p_list, listData data) {
    /* 创建一个节点,将数据放置进去 */
    list_t* newNode = (list_t*)malloc(sizeof(list_t));
    if (newNode == NULL) {
        return ERROR;
    }
    memcpy(&newNode->data, &data, sizeof(listData));
    newNode->next = NULL;

    /* 找到最后一个节点的位置 */
    list_t* p = p_list; /* 头指针 */
    while (p->next != NULL) {
        p = p->next;
    }

    /* 插入为最后一个节点 */
    newNode->next = p->next;
    p->next = newNode;
    return OK;
}

uint32_t list_insert(list_t* p_list, uint32_t index, listData data) {
    if (index <= 0) {
        /* 节点从1开始,0属于无效节点 */
        return ERROR;
    }

    /* 查找插入的位置 */
    uint32_t i = 1; /* 从第一个节点开始 */
    list_t* p = p_list; /* 指向头指针 */
    while (p != NULL && i < index) {
        /* 当前节点不为NULL,且当前节点数仍小于被插入的位置,则继续遍历 */
        p = p->next; /* 指向下一个节点 */
        i++; /* 节点数++ */
    }

    /* 遍历完成,检查有效性,如果p为NULL的话,说明index超过链表长度了,无法插入 */
    if (p == NULL) {
        return ERROR;
    }

    /* 创建一个节点,将数据放置进去 */
    list_t* newNode = (list_t*)malloc(sizeof(list_t));
    if (newNode == NULL) {
        return ERROR;
    }
    memcpy(&newNode->data, &data, sizeof(listData));
    newNode->next = NULL;

    /* 从找到的位置的后面插入到链表 */
    newNode->next = p->next;
    p->next = newNode;
    return OK;
}

uint32_t list_delete(list_t* p_list, uint32_t index) {
    if (index <= 0) {
        return ERROR;
    }

    /* 找到这个节点的前一个节点 */
    uint32_t i = 1;
    list_t* p = p_list;
    while (p != NULL && i < index) {
        p = p->next;
        i++;
    }

    if (p == NULL) {
        return ERROR;
    }

    list_t* q = p->next; /* 记录当前节点的下一个节点位置 */
    p->next = q->next;
    free(q);
    return OK;
}

uint32_t list_merge(list_t* p_list, uint32_t index, list_t* p_list_2) {
    if (index <= 0) {
        return ERROR;
    }

    /* 找到p_list要插入的位置 */
    uint32_t i = 1;
    list_t* p = p_list->next;
    while (p != NULL && index < i) {
        p = p->next;
        i++;
    }

    if (p == NULL) {
        return ERROR;
    }

    /* 找到p_list_2的最后一个节点的位置 */
    list_t* p2 = p_list_2;
    while (p2->next != NULL) {
        p2 = p2->next;
    }

    p2->next = p->next;
    p->next = p_list_2->next;
    p_list_2->next = NULL; // list_2没有节点了,next = NULL
    return OK;
}

void list_reverse(list_t* p_list) {
    /* 逆序,原第一个节点是不需要动的,只需要最终将next = NULL即可 */
    node_t* temp = NULL;
    node_t* p = list_head->next; /* 头节点 */
    while (p != NULL && p->next != NULL) {
        temp = p->next; /* 当前节点的下一个节点,temp这个节点就可以移动了 */
        p->next = temp->next;
        temp->next = list_head->next;
        list_head->next = temp;
    }
}

void list_display(list_t* p_list) {
    list_t* p = p_list->next; /* 指向第一个节点 */

    int i = 1; /* 节点计数 */
    while (p != NULL) {
        printf("node[%d].data = %d\n", i, p->data);
        p = p->next;
        i++;
    }
}

测试代码 main.c

#include <stdio.h>
#include <stdlib.h>

#include "list.h"

int main(int argc, char const *argv[])
{
    list_t* list_head = list_init();

    list_insert(list_head, 1, 10); // 10
    list_insert(list_head, 2, 20); // 10 20
    list_insert(list_head, 2, 30); // 10 30 20
    list_insert(list_head, 3, 40); // 10 30 40 20

    list_insert_head(list_head, 1); // 1 10 30 40 20
    list_insert_head(list_head, 2); // 2 1 10 30 40 20
    list_insert_head(list_head, 3); // 3 2 1 10 30 40 20

    list_insert_tail(list_head, 100); // 3 2 1 10 30 40 20 100
    list_insert_tail(list_head, 200); // 3 2 1 10 30 40 20 100 200
    list_insert_tail(list_head, 300); // 3 2 1 10 30 40 20 100 200 300

    list_delete(list_head, 1); // 2 1 10 30 40 20 100 200 300
    list_delete(list_head, 2); // 2 10 30 40 20 100 200 300
    list_delete(list_head, 3); // 2 10 40 20 100 200 300

    list_t* list_head_2 = list_init();

    list_insert(list_head_2, 1, 1000); // 1000
    list_insert(list_head_2, 2, 2000); // 1000 2000
    list_insert(list_head_2, 2, 3000); // 1000 3000 2000

    list_merge(list_head, 2, list_head_2); // 2 1000 3000 2000 10 40 20 100 200 300

    // list_clear(list_head);

    list_display(list_head);
    // list_display(list_head_2);

    list_reverse(list_head);
    list_display(list_head); // 300 200 100 20 40 10 2000 3000 1000 2

    list_uninit(&list_head);
    list_uninit(&list_head_2);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值