C数据结构——单链表 创建与基本使用

源码+注释

//
// Created by Lenovo on 2022-03-16-下午 9:41.
// 作者:小象
// 版本:1.0
//

#include <stdio.h>
#include <malloc.h>

#define LIST_NUM1 10
#define LIST_NUM2 10

typedef enum {
    ERROR,
    OK
} Status;

typedef enum {
    FALSE,
    TRUE
} boolean;

typedef int ElemType;

typedef struct LNode { // 单链表的定义
    // 空间对齐:LNode 8-8 -> 16
    ElemType data; // 数据域 int 4s
    struct LNode *next; // 指针域 结构体 8
} LNode, *LinkList; // LinkList 为指向结构体 LNode的指针类型

Status InitList(LinkList list); // 单链表的初始化

void CreateListHead(LinkList list, int n); // 单链表的创建 头插法

void CreateListTail(LinkList list, int n); // 单链表的创建 尾插法

Status GetElem(LinkList list, int i, ElemType *e); // 单链表取值

LNode *FindElem(LinkList list, ElemType *e); // 查找单链表的值

Status InsertElem(LinkList list, int i, ElemType *e); // 单链表插入一个元素

Status DeleteElem(LinkList list, int i, ElemType *e); // 删除单链表中的一个元素

Status ClearList(LinkList list); // 单链表整表删除

boolean IsEmpty(LinkList list); // 判断链表是否为空

/**
 * <h2>单链表的使用</h2>
 * @return 0
 */
int main() {

    // 1. 定义
    LNode List;
    // 2. 初始化 由于只有C++才能进行初始化 所以这里走个过场 后续代码须注意初始化问题
    printf("%d\n", InitList(&List));
    // 3. 创建线性表
    CreateListHead(&List, LIST_NUM1);
    CreateListTail(&List, LIST_NUM2);
    // 4. 取值
    int num1;
    GetElem(&List, 2, &num1);
    printf("%d\n", num1);
    // 5. 查找 按值查找
    int num2 = 8;
    printf("%d\n", FindElem(&List, &num2)->data);
    // 6. 插入
    printf("%d\n", InsertElem(&List, 11, &num2));
    // 7. 删除
    DeleteElem(&List, 2, &num2);
    printf("%d\n", num2);
    // 8. 整表删除
    printf("%d\n", ClearList(&List));
    // 9. 判表空
    printf("%d\n", IsEmpty(&List));


    printf("\n%d%d%d%d", ERROR, OK, FALSE, TRUE);
    printf("\n%llu, %llu", sizeof(LNode), sizeof(LinkList));

    return 0;

}

Status InitList(LinkList list) {
    list = (LinkList) malloc(sizeof(LNode)); // 申请 LNode 数据类型大小的节点空间
    if (list == NULL) { // 如果申请不到 返回NULL 直接 ERROR
        return ERROR;
    }
    list->next = NULL; // 头结点的指针域置空
    list->data = 0; // 头结点放入初始表长0
    return OK; // 初始化成功
}

// 逆位序输入 n 个元素的值,建立带表头结点的单链表 list
void CreateListHead(LinkList list, int n) {
    LNode *temp;
    list->next = NULL; // 初始化 list
    for (int i = 0; i < n; i++) {
        temp = (LinkList) malloc(sizeof(LNode)); // 生成新结点 *temp
        temp->data = i + 1; // 输入元素赋值给新结点 *temp 的数据域
        temp->next = list->next; // 将新结点 *temp 插入头结点之后
        list->next = temp;
    }
    list->data = n;
}

// 正位序输入 n 个元素的值,建立带表头结点的单链表 list
void CreateListTail(LinkList list, int n) {
    LNode *pL = list; // 尾指针 pL 指向头结点
    LNode *temp;
    for (int i = 0; i < n; i++) {
        temp = (LinkList) malloc(sizeof(LNode)); // 生成新结点
        temp->data = i + 1; // 输入元素赋值给新结点 *temp 的数据域
        temp->next = NULL;
        pL->next = temp; // 将新结点 *temp 插入尾结点 *pL 之后
        pL = temp; // pL 指向新的尾结点 *temp
    }
    list->data = n;
}

// 在带头结点的单链表 list中根据序号 i 获取元素的值,用 e 返回 list中第 i 个数据元素的值
Status GetElem(LinkList list, int i, ElemType *e) {
    LNode *pL = list->next; // 初始化,pL指向首元结点,计数器 j 初值赋为 1
    int j = 1;
    while (pL && j < i) { // 顺链域向后扫描,直到 pL为空或 pL指向第 i 个元素
        pL = pL->next; // pL 指向下一结点
        ++j; // 计数器 j 相应加 1
    }
    if (!pL || j > i) {
        return ERROR;
    }
    *e = pL->data; // 取第 i 个结点的数据域
    return OK;
}

// 在带头结点的单链表 list 中查找值 e 的元素
LNode *FindElem(LinkList list, ElemType *e) {
    LNode *pL = list->next;
    while (pL && pL->data != *e) { // 顺链域向后扫描,直到 pL为空或 pL所指结点的数据域等于 e
        pL = pL->next; // pL 指向下一结点
    }
    return pL; // 查找成功返回值为 e 的结点地址pL,查找失败 pL为 NULL
}

// 在带头结点的单链表 list 中第 i 个位置插入值为 e 的新结点
Status InsertElem(LinkList list, int i, ElemType *e) {
    LNode *pL = list;
    int j = 1;
    while (pL && j < i) { // 查找第 i-1 个结点,pL指向该结点
        pL = pL->next;
        ++j;
    }
    while (!pL || j > i) { // i>链表长度+1 或 i<1 时,插入位置不合理
        return ERROR;
    }
    LNode *temp = (LinkList) malloc(sizeof(LNode)); // 生成新结点 *temp
    temp->data = *e; // 将结点 *temp的数据域置为 e

    temp->next = pL->next; // 将结点 *temp的指针域指向结点 pL中第 i 个结点
    pL->next = temp; // 将结点 *pL的指针域指向结点 *temp
    list->data++;
    return OK;
}

// 在带头结点的单链表 list 中,删除第 i 个元素
Status DeleteElem(LinkList list, int i, ElemType *e) {
    LNode *pL = list, *temp;
    int j = 1;
    while ((pL->next) && j < i) { // 查找第 i-1 个结点,pL指向该结点
        pL = pL->next;
        ++j;
    }
    while (!(pL->next) || j > i) { // 当 i>链表长度 或 i<1 时,删除位置不合理
        return ERROR;
    }
    temp = pL->next; // 临时保存被删结点的地址以备释放
    pL->next = temp->next; // 改变删除结点前驱结点的指针域 这两句可以改为 pL-next = pL->next->next;

    *e = temp->data;
    free(temp); // 释放删除结点的空间
    list->data--;
    return OK;
}

Status ClearList(LinkList list) {
    LNode *pL, *temp;
    pL = list->next;
    while (pL) {
        temp = pL->next;
        free(pL); // 释放内存
        pL = temp;
    }
    list->next = NULL; // 指针置空,防止产生野指针
    list->data = 0;
    return OK;
}

boolean IsEmpty(LinkList list) {
    if (list->next == NULL) {
        return TRUE;
    } else {
        return FALSE;
    }
}

void PrintList(LinkList list) {
    LNode *pL;
    int count = 0;
    printf("->{%2d}", list->data);
    for (pL = list->next; pL != NULL; pL = pL->next) {
        printf("->");
        printf("(%2d)", pL->data);
        if (++count % 10 == 0 && count != list->data) {
            printf("\n        ");
        }
    }
    printf("\n");
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小丶象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值