自己手写一个单向链表【C风格】

news2025/3/12 17:53:46
//单链表
#include <iostream>
#define MAX_SIZE 20
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int ElemType;//元素的类型
typedef int Status;//返回状态

typedef struct Node
{
    ElemType data;//链表中保存的数据
    struct Node* next;//指向下一个节点
};

typedef struct Node* linkList;//定义单链表,指针

//初始化,L是指针的指针
Status InitList(linkList* L)
{
    (*L) = (linkList)malloc(sizeof(Node));//c语言分配内存头节点
    if ((*L) == NULL)
        return ERROR;//没有成功分配内存
    (*L)->next = NULL;//头节点的下一节点为空,此时只有一个空节点,头结点不包含
    return OK;
}

//清空
Status ClearList(linkList* L)
{
    linkList p, q;
    p = (*L)->next;//拿到第一个节点
    while (p != NULL)
    {
        q = p->next;//提前保存下一个节点以及后面内容
        free(p);//释放拿到的节点内存
        p = q;//继续拿下一个节点
    }
    (*L)->next = NULL;//最后将头结点的下一节点置为空
    return OK;
}

//是否为空
Status isListEmpty(linkList L)
{
    if (L->next != NULL) 
        return FALSE;
    return TRUE;
}

//返回长度
int ListLength(linkList L)
{
    int i = 0;
    linkList p = L->next;//指向头结点的下一节点
    while (p)
    {
        i++;
        p = p->next;
    }
    return i;
}

//获取指定位置元素
Status GetElem(linkList L, int i, ElemType *e)
{
    linkList p = L->next;
    int j = 1;//从1开始,如果j==1,就正是第一个节点,头结点不算
    while ((p != NULL) && (j < i))
    {
        j++;
        p = p->next;
    }
    if (p == NULL || j > i)
    {
        return ERROR;
    }
    *e = p->data;
    return OK;
}

//定位元素
int LocateElem(linkList L, ElemType e)
{
    int i = 1;
    linkList p = L->next;
    while (p)
    {
        if (p->data == e)
            return i;//返回元素所在的节点位置,从1开始
        i++;
        p = p->next;
    }
    return ERROR;
}

//增加元素
Status ListInsert(linkList* L, int i, ElemType e)
{
    linkList p, q;
    p = *L;//增加元素时是增加到对应位置的上一节点,比如1是在头节点之后
    int j = 1;
    while ((p != NULL) && j < i)
    {
        j++;
        p = p->next;
    }
    if (!p || j > i)return ERROR;
    q = (linkList)malloc(sizeof(Node));
    if (q == NULL)return ERROR;
    q->data = e;
    q->next =  p->next;//上一节点的后面节点赋予添加节点的后面
    p->next = q;//再把添加节点赋予上一节点的后面
    return OK;

}

//删除元素
Status ListDelete(linkList* L, int i)
{
    int j = 1;
    linkList p = *L, q;//删除元素,也要知道上一节点
    while (p && j < i)
    {
        j++;
        p = p->next;
    }
    if (!p || j > i)return ERROR;

    if (p->next == NULL)return ERROR;

    //***提前保存需要删除的内存****
    q = p->next;//保存后面第一个节点

    p->next = p->next->next;//让后面第二个节点开始接到后面第一个节点位置

    //特别注意,不能是free(p->next)因为已经变化了
    free(q);//再释放后面第一个的内存

    return OK;
}

//遍历显示
Status ListTraverse(linkList L)
{
    linkList p = L->next;
    while (p)
    {
        printf("%d-->", p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
    
}

//创建头部n个新的随机元素
Status CreatListHead(linkList* L, int n)
{
    srand((unsigned)time(NULL));//随机数种子,根据时间变化
    linkList p;
    *L = (linkList)malloc(sizeof(Node));
    if((*L) == NULL)return ERROR;
    (*L)->next = NULL;
    while (n--)
    {
        p = (linkList)malloc(sizeof(Node));
        if((p) == NULL)return ERROR;
        p->data = rand() % 100 + 1;
        p->next = (*L)->next;//新节点后面接上头结点后面的节点
        (*L)->next = p;//一直再头结点后面添加新节点
    }
    return OK;

}

//创建尾部
Status CreatListTail(linkList* L,int n)
{
    srand((unsigned)time(NULL));
    linkList p, q;
    *L = (linkList)malloc(sizeof(Node));
    if ((*L) == NULL)return ERROR;
    q = *L;
    while (n--)
    {
        p = (linkList)malloc(sizeof(Node));
        if ((p) == NULL)return ERROR;
        p->data = rand() % 100 + 1;
        q->next = p;//尾部后面一直接新节点
        q = p;//更换尾部
    }
    q->next = NULL;
    return OK;
}


int main()
{
    linkList L;
    ElemType e = 0;
    Status res;
    int i, j;

    res = InitList(&L);
    printf("初始化后的长度:%d\n", ListLength(L));

    for (i = 0; i < 5; i++)
    {
        res = ListInsert(&L, 1, i);
        if (!res)printf("插入元素失败!\n");
    }
    printf("插入5个元素后:\n");
    ListTraverse(L);
    printf("插入5个元素后是否为空:%d(1:是  0:否)\n", res);
    printf("插入5个元素后的长度:%d\n", ListLength(L));

    res = isListEmpty(L);
    printf("是否为空:%d(1:是  0:否)\n", res);
    
    res = ClearList(&L);
    printf("清空后后的长度:%d\n", ListLength(L));
    printf("清空后是否为空:%d(1:是  0:否)\n", res);

    //重新插入
    for (i = 0; i < 10; i++)
    {
        res = ListInsert(&L, 1, i);
        if (!res)printf("插入元素失败!\n");
    }
    printf("插入10个元素后:\n");
    ListTraverse(L);
    printf("插入10个元素后的长度:%d\n", ListLength(L));

    GetElem(L, 5, &e);
    printf("第5个元素为:%d\n",e);

    //删除测试
    j = ListLength(L);
    res = ListDelete(&L, j + 1);
    if (res == ERROR)
        printf("删除第%d元素失败!\n", j + 1);
    else
        printf("删除第%d元素成功!\n", j);

    res = ListDelete(&L, j);
    if (res == ERROR)
        printf("删除第%d元素失败!\n", j);
    else
        printf("删除第%d元素成功!\n", j);
    printf("删除后:\n");
    ListTraverse(L);
    
    if (ListDelete(&L, 5))
    {
        printf("删除第五个元素成功!\n");
        
    }
    ListTraverse(L);
    ClearList(&L);

    CreatListHead(&L, 20);
    printf("头部创建:\n");
    ListTraverse(L);
    ClearList(&L);

    printf("尾部创建:\n");
    CreatListTail(&L, 20);
    ListTraverse(L);
    
    ClearList(&L);

    free(L);

    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1695704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【字典树(前缀树) 异或 离线查询】1707. 与数组中元素的最大异或值

本文涉及知识点 字典树&#xff08;前缀树&#xff09; 位运算 异或 离线查询 LeetCode1707. 与数组中元素的最大异或值 给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries &#xff0c;其中 queries[i] [xi, mi] 。 第 i 个查询的答案是 xi 和任何 nums 数组…

自定义一个复杂的React Table表格组件-06

前面基本了解了组件的基本用法&#xff0c;在本节会实现一个更高级的例子。另外需要注意本节代码是采用V15版本的createClass()、React.DOM和JSX实现的&#xff0c;有时间的同学可以改成类实现的方式。 html的世界中最复杂的UI控制就是表格了&#xff0c;原因是table它依赖本地…

Vitis HLS 学习笔记--控制驱动TLP-处理deadlock

目录 1. 简介 2. 代码解析 2.1 HLS kernel代码 2.2 查看接口报告 2.3 TestBench 2.4 Dataflow 报告 3. Takeaways 4. 总结 1. 简介 本文是对《Hardware Acceleration Tutorials: FIFO Sizing for Performance and Avoiding Deadlocks》实验内容的详细解释。 首先需要…

AI视频教程下载:用提示工程在GPT商店构建10个GPTs

你将学到什么&#xff1f; 深入了解ChatGPT平台和GPT商店的生态系统。 开发为多样化应用定制GPT模型的专业知识。 掌握高效内容生成的AI自动化技术。 学习高级提示工程以优化ChatGPT输出。 获取构建AI驱动的数字营销和广告解决方案的技能。 了解如何为SEO写作和优化创建专…

从0开始学统计-多个婴儿连续夭折是谋杀吗?

1.什么是小概率事件&#xff1f; 小概率事件是指在一次随机试验中发生概率非常低的事件。一般来说&#xff0c;小概率事件的发生概率远低于一定的阈值&#xff0c;通常取0.05或0.01。在统计学中&#xff0c;这些阈值被称为显著性水平&#xff08;significance level&#xff0…

CIC滤波器

CIC滤波器结构简单&#xff0c;没有乘法器&#xff0c;只有加法器、积分器和寄存器&#xff0c;适合工作在高抽样率条件下&#xff0c;而且CIC滤波器是一种基于零点相消的FIR滤波器。 CIC滤波器分为单级和多级滤波器。 1.在单极滤波器中&#xff1a; 当CIC滤波器的长度M远大于…

【css3】04-css3转换

目录 1 2D转换 2 3D转换 3 案例&#xff1a;旋转的魔方 1 2D转换 ## 2D转换 ☞ 位移 transform: translate(100px,100px); 备注&#xff1a; 位移是相对元素自身的位置发生位置改变 ☞ 旋转 transform: rotate(60deg); 备注&am…

LabVIEW虚拟测试实验室开发

LabVIEW虚拟测试实验室开发 在当代的科技和工业进步中&#xff0c;测试与测量扮演着至关重要的角色。随着技术的发展&#xff0c;测试系统也变得日益复杂和成本昂贵&#xff0c;同时对测试结果的准确性和测试过程的效率要求越来越高。开发了一种基于LabVIEW的虚拟测试实验室的…

新能源汽车的电驱热管理

前言 新能源汽车的电驱热管理是指维持电动汽车电池、电机和电控系统在适宜的工作温度范围内&#xff0c;保障车辆高效、安全、稳定运行的技术方案。随着新能源汽车的快速发展和普及&#xff0c;电驱热管理技术也日益成为关注焦点。本文将从电池、电机和电控系统三个方面介绍新…

k8s集群的声明式管理资源

一 声明式管理方法 1 适合于对资源的修改操作&#xff08;陈述式方式修改资源非常不方便&#xff09; 2 声明式资源管理方法依赖于yaml资源配置清单文件对资源进行管理 资源配置清单文件有两种格式&#xff1a;yaml&#xff08;人性化&#xff0c;易读&#xff09;&#xff…

中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; 中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制https://mp.weixin.qq.com/s/ycNgYzACwkYZbo6k0Zqtcw 未来20年&#xff0c;我国将决战全面建成社会主义现代化国家&…

杰理-耳机进入关机关闭内内置触摸-节省功耗

杰理-耳机进入关机关闭内内置触摸-节省功耗 if (__this->init 0) {return LP_TOUCH_SOFTOFF_MODE_LEGACY; }if ((__this -> softoff_mode LP_TOUCH_SOFTOFF_MODE_ADVANCE) && (__this->softoff_keep 0)) {lp_touch_key_disable(); } __this->softoff_k…

安全设计 | Microsoft 威胁建模工具Threat Modeling Tool安装、使用及威胁生成原理详解(文末附样例)

1. 概览 微软威胁建模工具&#xff08;Threat Modeling Tool&#xff09;是 Microsoft 安全开发生命周期 (SDL&#xff0c;Security Development LifeCycle) 的核心要素。 当潜在安全问题处于无需花费过多成本即可相对容易解决的阶段&#xff0c;软件架构师可以使用威胁建模工…

对vue3/core源码ref.ts文件API的认识过程

对toRef()API的认识的过程: 最开始认识toRef()是从vue3源码中的ref.ts看见的,右侧GPT已经举了例子 然后根据例子,在控制台输出ref对象是什么样子的: 这就是ref对象了,我们根据对象中有没有__v_isRef来判断是不是一个ref对象,当对象存在且__v_isRef true的时候他就判定为是一个…

F28034中断

DSP中断 中断中断概述中断机制 中断 当CPU正在执行程序时&#xff0c;由于发生了某种随机的事件&#xff08;外部或内部&#xff09;&#xff0c;使CPU的执行中断&#xff0c;转而去执行某一段特殊的程序&#xff08;中断子程序或中断处理程序&#xff09;&#xff0c;以处理该…

cs与msf权限传递,以及mimikatz抓取win2012明文密码

目录 解释参数 foreign http foreign https cs与msf权限传递 Cobalt Strike会话传递到Metasploit Framework Cobalt strike上的操作 ​编辑​编辑​编辑 Metasploit Framework上的操作 传递会话 Metasploit Framework会话传递到Cobalt Strike Cobalt strike上的操作…

Tina-Linux -- 3. LVGL测试

参考韦东山 – Tina_Linux_图形系统_开发指南 Tina-linux lvgl 配置 环境配置 进入Tina-SDK根目录 source build/envsetup.sh lunch XXX平台名称 make menuconfigLVGL Gui --->Littlevgl --->< > lv_demo<*> lv_examples &#xff08;lvgl官方demo&#…

监控监测管理系统产品规格说明书(实际原件参考)

【智慧工地】监控监测管理系统产品规格说明书编制模板 一、引言 二、 项目概述 三、 总体需求 四、 功能需求 4.1 概述 4.2 业务功能概要描述 4.3 功能性需求 4.4 功能描述 五、 非功能性需求 5.1 用户界面需求 5.2 软硬件环境需求 5.3 产品质量需求 5.4 接口需求 5.5 其他需求…

HarmonyOS 鸿蒙应用开发 - 多态样式 stateStyles

前言&#xff1a;Styles和Extend仅仅应用于静态页面的样式复用&#xff0c;stateStyles可以依据组件的内部状态的不同&#xff0c;快速设置不同样式&#xff0c;类似于css伪类&#xff0c;但语法不同。 ArkUI提供以下四种状态&#xff1a; focused&#xff1a;获焦态。normal&…

MySQL库/表/数据的操作

文章目录 1.数据库操作1.1 创建、删除、查看和修改1.2 编码格式1.3 备份和恢复 2.表的操作2.1 创建表2.2 存储引擎2.3 查看表、修改表、删除表 3.数据类型3.1整数类型3.2字节类型(bit)3.3浮点类型(bit)3.4 decimal3.5 字符串类型3.6 日期和时间类型3.7 enum和set关于如何查找想…