当前位置: 首页 > article >正文

嵌入式培训之数据结构学习(三)gdb调试、单向链表练习、顺序表与链表对比

目录

一、gdb调试

(一)一般调试步骤与命令

(二)找段错误(无下断点的地方)

(三)调试命令

二、单向链表练习

1、查找链表的中间结点(用快慢指针)

2、找出链表倒数第k个结点(用快慢指针)

3、链表的逆序

4、链表的插入排序

三、顺序表和链表对比

四、循环链表

一、gdb调试

(一)一般调试步骤与命令

1、gcc -g (调试版本,内含调试信息与源码;eg:gcc -g main.c linklist.c)

2、gdb a.out(调试可执行文件,eg:gdb ./a.out)

3、b fun.c:36 设置断点,运行到这个位置,程序自动暂停

(b :100 默认停在main.c的100行;

   b fun.c : 36  停在fun.c的36行

   b 函数名    eg: b InserPosLinkList)

4、 运行(出现页面要输入则输入)

5、n 执行下一步  步过(如果是函数,直接调用结束)

      步入自定义函数(系统函数不入)

6、使用p命令,查看变量或指针等数据

(p  变量:显示变量值,eg:p len

   p  指针:看地址,eg:p *data)

7、q命令 退出(y)

(二)找段错误(无下断点的地方)

1、gcc -g  (加上调试选项-g,eg:gcc main.c linklist.c -g)

2、gdb a.out (调试可执行文件,eg:gdb ./a.out)

3、按  r(run)  直接开始运行

4、重现错误

5、where 找出段错误的位置(出现栈结构信息,从下往上看,找到第一个不是自己写的往后退一个)

    eg:#0(第一个不是自己写的,往后退一个)

            #1(此处出现段错误)

            #2

(三)调试命令

二、单向链表练习

1、查找链表的中间结点(用快慢指针)

(1)算法实现:

LinkNode* FindMidLinkList(LinkList*ll)

// 定义函数,功能是查找链表的中间节点,参数为链表头指针,返回链表节点指针
{
    LinkNode* fast = ll->head; // 初始化快指针,指向链表头节点
    LinkNode* slow = ll->head; // 初始化慢指针,指向链表头节点
    while(fast) // 当快指针不为空时,进行循环
    {
        fast = fast->next; // 快指针向前移动一个节点
        if(NULL == fast) // 检查快指针是否为空(即到达链表末尾)
        {
            break; // 如果为空,跳出循环
        }
        slow = slow->next; // 慢指针向前移动一个节点
        fast = fast->next; // 快指针再向前移动一个节点
    }
    return slow; // 循环结束,返回慢指针,此时慢指针指向链表中间节点
}

(2)调试:

2、找出链表倒数第k个结点(用快慢指针)

(1)算法实现:

LinkNode* FindLastKLinkList(LinkList*ll,int k)

// 定义函数,功能是查找链表倒数第k个节点,参数为链表头指针和整数k,返回链表节点指针
{

    int len = GetSizeLinkList(ll);
    if(k < 0 || k > len)
    {
        return NULL;
    }
    LinkNode* slow = ll->head; // 初始化慢指针,指向链表头节点
    LinkNode* fast = ll->head; // 初始化快指针,指向链表头节点
    for(int i = 0 ;i < k ;i++) // 循环k次
    {
        fast = fast->next; // 快指针向前移动一个节点,共移动k次
    }
    while(fast) // 当快指针不为空时,进行循环
    {
        fast =fast->next; // 快指针向前移动一个节点
        slow= slow->next; // 慢指针向前移动一个节点
    }
    return slow; // 循环结束,返回慢指针,此时慢指针指向链表倒数第k个节点
}

(2)调试:

3、链表的逆序

(1)图解

(2)算法实现

int RevertLinkList(LinkList* ll)
{
    LinkNode* prev = NULL; // 定义指针prev,用于指向当前节点的前一个节点,初始化为NULL
    LinkNode* tmp = ll->head; // 定义指针tmp,指向链表头节点,用于遍历链表
    LinkNode* next = tmp->next; // 定义指针next,指向tmp的下一个节点,用于保存tmp后续节点,防止链表断裂
    int len = GetSizeLinkList(ll); // 调用GetSizeLinkList函数获取链表长度并存储在len中
    if(len<2) // 如果链表长度小于2,即链表为空或只有一个节点
    {
        return 1; // 无需反转,直接返回1
    }
    while (1) // 进入无限循环,用于遍历并反转链表
    {
        tmp->next = prev; // 将当前节点tmp的next指针指向它的前一个节点prev,实现当前节点的反转
        prev = tmp; // 将prev指针移动到当前节点tmp的位置,为下一轮循环做准备
        tmp = next; // 将tmp指针移动到原本保存的下一个节点next的位置
        if (NULL == tmp) break; // 如果tmp指向NULL,说明已经遍历到链表末尾,跳出循环
        next = next->next; // 将next指针移动到tmp当前指向节点的下一个节点,为下一轮循环保存后续节点
    }
    ll->head = prev; // 将链表的头节点更新为反转后链表的头节点(即原链表的尾节点)
    return 0; // 成功反转链表,返回0
}

4、链表的插入排序

LinkList* InsertSortLinklist(LinkList* ll)
{
    LinkNode* pins = ll->head; // 定义指针pins,指向链表头节点,用于定位插入位置
    LinkNode* ptmp = pins->next; // 定义指针ptmp,指向头节点的下一个节点,作为待插入节点
    LinkNode* next = ptmp->next; // 定义指针next,指向ptmp的下一个节点,用于保存ptmp后续节点,防止链表断裂
    ptmp->next = NULL; // 将待插入节点ptmp的next指针置空,使其暂时脱离原链表
    ll->head->next = NULL; // 将原链表头节点的next指针置空,原链表头节点成为新链表的第一个节点,且新链表初始只有这一个节点

    while(1) // 进入无限循环,用于遍历链表并进行插入排序
    {
        pins = ll->head; // 每次循环开始,将pins重新指向新链表头节点,从新链表头部开始寻找插入位置
        // 当pins后面还有节点,且待插入节点ptmp的年龄值大于pins节点和pins下一个节点的年龄值时
        while(pins->next && ptmp->data.age > pins->data.age && ptmp->data.age > pins->next->data.age) 
        {
            pins = pins->next; // 移动pins指针,向后寻找合适的插入位置
        }

        if(pins->data.age > ptmp->data.age) // 如果找到的位置pins节点的年龄值大于待插入节点ptmp的年龄值
        {
            ptmp->next = ll->head; // 将待插入节点ptmp的next指针指向新链表头节点
            ll->head = ptmp; // 更新新链表头节点为ptmp,即将ptmp插入到新链表头部
        }
        else // 否则(即pins节点的年龄值小于等于ptmp的年龄值)
        {
            ptmp->next = pins->next; // 将待插入节点ptmp的next指针指向pins的下一个节点
            pins->next = ptmp; // 将pins的next指针指向ptmp,即将ptmp插入到pins之后
        }
        ptmp = next; // 将ptmp指针移动到原本保存的下一个节点next的位置,准备处理下一个待插入节点
        if(NULL == ptmp) // 如果ptmp指向NULL,说明已经处理完所有节点
        {
            break; // 跳出循环
        }
        next = next->next; // 将next指针移动到ptmp当前指向节点的下一个节点,为下一轮循环保存后续节点
        ptmp->next = NULL; // 将待插入节点ptmp的next指针置空,使其暂时脱离原链表
    }
    return ll; // 返回排序后的链表头指针
}

三、顺序表和链表对比

1、存储方式
        顺序表 是一段连续的存储单元
        链表 是逻辑结构连续物理结构(在内存中的表现形式)不连续(因为是通过malloc获得的)

2、 时间性能
        查找 :          顺序表O(1)      //按规则放,找的时候按规则找;支持随机访问

                              链表  O(n)        //只能从第一个往后找

        插入和删除:顺序表 O(n)      //整体前移与后移

                             链表   O(1)        //一次性改(只需把一个节点连上),与链表数据量无关

3、 空间性能
        顺序表 需要预先分配空间,大小固定;只放数据
        链表, 不需要预先分配,大小可变,动态分配;数据 + 指针域

四、循环链表

       1、 简单的来说,就是将原来单链表中最有一个元素的next指针指向第一个元素或

头结点,链表就成了一个环,头尾相连,就成了循环链表。circultlar linker list.

       2、  注意非空表,和空表。多数会加入头结点。

       3、 原来结束的条件是 p->next != NULL ------->>>>> p-next != Head 

4、练习:判断链表是否有环(用快慢指针)

int IsRingLinkList(LinkList* ll)  

// 定义函数判断链表是否有环,参数为链表指针,返回整型(0表示无环,1表示有环)
{
        LinkNode* fast = ll->head;  // 定义快指针fast,初始指向链表头节点
        LinkNode* slow = ll->head;  // 定义慢指针slow,初始也指向链表头节点
 
        while (fast)  // 当快指针不为空时进入循环(快指针为空时说明已遍历到链表末尾,无环)
        {
                fast = fast->next;  // 快指针先移动一步(每次移动两步的第一步)
                if (NULL == fast)  // 检查快指针移动后是否为空
                {
                        return 0;  // 若为空,说明链表无环,返回0
                }
 
                if (slow == fast)  // 检查慢指针和快指针是否相遇(相遇则说明有环)
                {
                return 1;  // 若相遇,返回1表示有环
                }
                fast = fast->next;  // 快指针再移动一步(完成每次移动两步)
                slow = slow->next;  // 慢指针每次移动一步
        }
        return 0;  // 循环结束后仍未相遇,说明链表无环,返回0
}

相关文章:

嵌入式培训之数据结构学习(三)gdb调试、单向链表练习、顺序表与链表对比

目录 一、gdb调试 &#xff08;一&#xff09;一般调试步骤与命令 &#xff08;二&#xff09;找段错误&#xff08;无下断点的地方&#xff09; &#xff08;三&#xff09;调试命令 二、单向链表练习 1、查找链表的中间结点&#xff08;用快慢指针&#xff09; 2、找出…...

虚拟机安装CentOS7网络问题

虚拟机安装CentOS7网络问题 1. 存在的问题1.1 CentOS7详细信息 2. 解决问题3.Windows下配置桥接模式 1. 存在的问题 虽然已经成功在虚拟机上安装了CentOS7&#xff0c;但是依旧不能上网。 1.1 CentOS7详细信息 [fanzhencentos01 ~]$ hostnamectlStatic hostname: centos01Ic…...

零基础学Java——终章:核心知识点与面试总结

Java核心知识点与面试总结 本文档旨在总结Java的核心知识点&#xff0c;并提供常见的面试问题与解答&#xff0c;帮助学习者巩固知识和准备面试。 目录 零基础学Java——大纲合集 Java基础 1. Java概述 JDK (Java Development Kit): Java开发工具包&#xff0c;包含Java的…...

迅为RK3588开发板安卓GPIO调用APP运行测试

将网盘上的安卓工程文件复制到 Windows 电脑上。确保工程路径中使用英文字符&#xff0c;不包含中文。接着&#xff0c;启动 Android Studio&#xff0c;点击“Open”按钮选择应用工程文件夹&#xff0c;然后点击“OK”。由于下载 Gradle 和各种 Jar 包可能需要一段时间&#x…...

在一台CentOS服务器上开启多个MySQL服务

1. 创建目录 mkdir -p /data/mysql3307/{data,tmp,logs} # 赋权 chown -R mysql:mysql /data/mysql3307 chmod -R 750 /data/mysql3307 2.修改 /etc/my.cnf &#xff0c;添加[mysqld3307]实例配置组 [mysqld3307] # mysql服务的端口 port 3307 # 套接字文件存放路径 socket /…...

C#高级编程:IO和序列化

在 C# 编程中,输入输出(IO)和序列化是两个至关重要的概念,它们为数据的存储、读取以及在不同环境间的传输提供了强大的支持。无论是开发小型应用程序,还是构建复杂的企业级系统,深入理解并熟练运用 IO 和序列化技术都是必不可少的。​ 一、C# 中的 IO 基础​ 1、文件流…...

Unity 红点系统

首先明确一个&#xff0c;即红点系统的数据结构是一颗树&#xff0c;并且红点的数据结构的初始化需要放在游戏的初始化中&#xff0c;之后再是对应的红点UI侧的注册&#xff0c;对应的红点UI在销毁时需要注销对红点UI的显示回调注册&#xff0c;但是不销毁数据侧的红点注册 - …...

尼康VR镜头防抖模式NORMAL和ACTIVE的区别(私人笔记)

1. NORMAL 模式&#xff08;常规模式&#xff09; 适用场景&#xff1a;一般手持拍摄&#xff0c;比如人像、静物、风景或缓慢平移镜头&#xff08;如水平追拍&#xff09;等。工作特性&#xff1a; 补偿手抖引起的小幅度震动&#xff08;比如手持时自然的不稳&#xff09;&am…...

JMeter 中通过 WebSocket (WS) 协议发送和接收 Protocol Buffers (Proto) 消息

在 JMeter 中通过 WebSocket (WS) 协议发送和接收 Protocol Buffers (Proto) 消息&#xff0c;需要使用 JMeter WebSocket 插件&#xff0c;并结合 JSR223 脚本处理 Proto 的序列化和反序列化。以下是完整步骤&#xff1a; 1. 准备工作 1.1 安装 WebSocket 插件 下载插件&…...

从索引中排除 Elasticsearch 字段

作者&#xff1a;来自 Elastic Kofi Bartlett 说明如何配置 Elasticsearch 排除字段、为什么要这样做&#xff0c;以及应遵循的最佳实践。 更多阅读&#xff1a;Elasticsearch&#xff1a;inverted index&#xff0c;doc_values 及 source 想获得 Elastic 认证&#xff1f;了解…...

【Android】文件分块上传尝试

【Android】文件分块上传 在完成一个项目时&#xff0c;遇到了需要上传长视频的场景&#xff0c;尽管可以手动限制视频清晰度和视频的码率帧率&#xff0c;但仍然避免不了视频大小过大的问题&#xff0c;且由于服务器原因&#xff0c;网络不太稳定。这个时候想到了可以将文件分…...

超详细Docker教程

前言&#xff1a;大家在在Linux上部署mysql及其他软件时&#xff0c;大家想一想自己最大的感受是什么&#xff1f; 我相信&#xff0c;除了个别天赋异禀的人以外&#xff0c;大多数人都会有相同的感受&#xff0c;那就是麻烦。核心体现在三点&#xff1a; 命令太多了&#xff…...

Java项目拷打(外卖+点评)

一、点评星球&#xff08;黑马点评&#xff09; 1、项目概述 1.1、项目简介 本项目是基于Spring Boot与Redis深度整合的前后端分离的点评平台。系统以Redis为核心技术支撑&#xff0c;重点解决高并发场景下的缓存穿透、击穿、雪崩等问题&#xff0c;涵盖商户展示、优惠券秒杀…...

hadoop中了解yarm

Hadoop中的YARN&#xff08;Yet Another Resource Negotiator&#xff09;是一种新的Hadoop资源管理器&#xff0c;是一个通用资源管理系统&#xff0c;可为上层应用提供统一的资源管理和调度。以下是其相关介绍&#xff1a; 核心思想 将JobTracker的资源管理和作业调度/监控功…...

Android usb网络共享详解

Android usb网络共享详解 文章目录 Android usb网络共享详解一、前言二、USB网络共享使用的前提1、Android设备支持adb 并且打开usb开关2、原生Settings能看到USB网络共享开关3、代码中检测USB网络共享是否支持 三、Settings 中USB网络共享代码的部分代码1、Settings\res\xml\t…...

【数据库知识】Mysql进阶-高可用MHA(Master High Availability)方案

mysql高可用MHA&#xff08;Master High Availability&#xff09;方案 集群部署模式下的高可用方案一、高可用架构原理1. 核心组件2. 故障切换流程 二、详细部署步骤 (3节点集群)1. 环境准备2. 节点配置&#xff08;以 node1 为例&#xff09;3. 初始化集群4. 部署MySQL Route…...

Web 架构之会话保持深度解析

文章目录 一、引言二、会话保持的基本概念2.1 什么是会话2.2 为什么需要会话保持 三、会话保持的常见实现方式3.1 基于客户端的会话保持3.1.1 Cookie 方式3.1.2 URL 重写方式 3.2 基于服务器端的会话保持3.2.1 负载均衡器会话保持3.2.2 会话共享 四、会话保持可能遇到的问题及解…...

微信小程序仿淘宝拍照/照片点位识图、点位裁剪生图、图片裁剪组件、图片点位框选、裁剪生成图片,canvasToImg

实现效果 效果&#xff1a; 1.微信小程序仿淘宝拍照/照片点位识图、根据点位裁剪生图、图片可裁剪、图片高度可控 2.识别点位自动生成标准构图方案&#xff0c;支持手动微调实现像素级精准裁剪 3.可以根据接口识别的点位信息实现拍照/相册图片特征点自动识别并裁剪 实现步骤 …...

attention_weights = torch.ones_like(prompt_embedding[:, :, 0]):切片操作获取第二维度,第三维度

attention_weights = torch.ones_like(prompt_embedding[:, :, 0]):切片操作获取第1 维度,第二维度 attention_weights = torch.ones_like(prompt_embedding[:, :, 0]) 这行代码的作用是创建一个与 prompt_embedding[:, :, 0] 形状相同且所有元素都为 1 的张量,它用于初始化…...

Rust入门之高级Trait

Rust入门之高级Trait - 本文源码 引言 前面学习了迭代器&#xff08;Iterators&#xff09;&#xff0c;Iterator源码中就用到了关联类型的功能。关联类型就属于高级trait的内容&#xff0c;这次我们学习一下高级trait&#xff0c;了解关联类型等知识。关联类型看似和泛型相…...

从 Set、Map 到 WeakSet、WeakMap 的进阶之旅

在 ES5 时代&#xff0c;JavaScript 的数据结构主要依赖于两种类型&#xff1a;数组和对象。然而&#xff0c;随着应用规模的增长和复杂性上升&#xff0c;传统的数据结构越来越难以满足开发需求。比如&#xff0c;需要一个能自动去重的集合、一个支持任意类型键名的字典、一个…...

TTL (Time-To-Live) 解析

文章目录 TTL (Time-To-Live) 解析&#xff1a;网络与Java中的应用一、TTL的定义二、TTL在网络中的应用1. **路由和数据包的生命周期**2. **DNS中的TTL**3. **防止环路** 三、TTL在Java中的应用1. **缓存管理**2. **Java中的ThreadLocal**3. **网络通信中的TTL** 四、TTL的注意…...

Qt/C++开发监控GB28181系统/录像文件查询/录像回放/倍速播放/录像文件下载

一、前言 搞定了实时预览后&#xff0c;另一个功能就是录像回放&#xff0c;录像回放和视频点播功能完全一致&#xff0c;唯一的区别就是发送点播的sdp信息中携带了开始时间和结束时间&#xff0c;因为是录像文件&#xff0c;所以有这个时间&#xff0c;而实时视频预览这个对应…...

季报中的FPGA行业:U型反转,春江水暖

上周Lattice,AMD两大厂商相继发布2025 Q1季报,尽管恢复速度各异,但同时传递出FPGA行业整体回暖的复苏信号。 5月5日,Lattice交出了“勉强及格”的答卷,报告季度营收1亿2000万,与华尔街的预期基本相符。 对于这家聚焦在中小规模器件的领先厂商而言,按照其CEO的预期,长…...

嵌入式机器学习平台Edge Impulse图像分类 – 快速入门

陈拓 2025/05/08-2025/05/11 1. 简介 官方网址 https://edgeimpulse.com/ 适用于任何边缘设备的人工智能&#xff1a; Gateways - 网关 Sensors & Cameras - 传感器和摄像头 Docker Containers - Docker容器 MCUs, NPUs, CPUs, GPUs 构建数据集、训练模型并优化库以…...

web 自动化之 yaml 数据/日志/截图

文章目录 一、yaml 数据获取二、日志获取三、截图 一、yaml 数据获取 需要安装 PyYAML 库 import yaml import os from TestPOM.common import dir_config as Dir import jsonpathclass Data:def __init__(self,keyNone,file_name"test_datas.yaml"):file_path os…...

ARMV8 RK3399 u-boot TPL启动流程分析 --start.S

上电后运行的第一支文件&#xff1a;arch/arm/cpu/armv8/start.S CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK1 #include <asm/arch/boot0.h> 跳转到 arch/arm/include/asm/arch-rockchip/boot0.h CONFIG_SPL_BUILD1 b 1f ROCKCHIP_EARLYRETURN_TO_BROMno TINY_FRAMEWORKno …...

zst-2001 上午题-历年真题 计算机网络(16个内容)

网络设备 计算机网络 - 第1题 ac 计算机网络 - 第2题 d 计算机网络 - 第3题 集线器不能隔离广播域和冲突域&#xff0c;所以集线器就1个广播域和冲突域 交换机就是那么的炫&#xff0c;可以隔离冲突域&#xff0c;有4给冲突域&#xff0c;但不能隔离广播域&#xf…...

使用termius连接腾讯云服务器

使用termius连接腾讯云服务器 1.下载termius termius官网 安装配置教程 这里安装的window版本> 默认安装到C盘&#xff0c;不建议修改路径 可以选择谷歌登录&#xff0c;也可以不登录&#xff0c;软件是免费的&#xff0c;试用的是付费版本&#xff0c;不需要点 2.配置 这里…...

redis 命令大全整理

http://doc.redisfans.com/ 原网址 Redis 命令分类 Key(键) Key(键)命令 exists/del/keys/type/scanobject/move/dump/migratettl/pttl/persist/expireat/pexpireat/expire/pexpirerename/renamenxsort/randomkey/restoreexists 语法:exists key [key ...] 检查一个或多…...