【数据结构】单链表解析+完整代码(插入、删除、尾插法、头插法、按值和按位查找、前插和后插)带头结点和不带两种实现

文章目录

      • 3.1 单链表
        • 3.1.1 单链表的定义
        • 3.1.2 单链表的插入
          • A.按位序插入(带头结点)
          • B.按位序插入(不带头结点)
          • C.指定结点的后插操作
          • D.指定结点的前插操作
        • 3.1.3 单链表的删除
          • A.按位序删除
          • B.删除指定结点
        • 3.1.4 单链表的查找
          • A.按位查找
          • B.按值查找
        • 3.1.5 单链表的建立
          • A.尾插法
          • B.头插法
        • *完整代码 单链表带头结点
        • *完整代码 单链表不带头结点

3.1 单链表

3.1.1 单链表的定义
  • 定义

    线性表的链式存储。

    • 结点结构:data+next(结点自身的数据+指向后继的指针)

    • 特点:元素分散在内存中,非随机存取的存储结构。

    • 局限性:无法逆向检索,有时不方便。(双链表可双向检索)

//定义单链表节点类型
typedef struct LNode{ElemType data; //数据域Struct LNode *next; //指针域,指向下一个结点
}LNode,*LinkList;
//注:
//LNode —— 强调返回的是一个结点
//LinkList —— 强调的是一个单链表
  • 初始化——带头结点

    //带头结点初始化
    bool InitList(LinkList &L){L=(LNode*)malloc(sizeof(LNode)); //为头结点分配内存if(L==NULL)return false; //内存不足,分配失败L->next=NULL; //头结点后还没有结点return true;
    }//带头结点判空
    bool Empty(LinkList L){if(L->next==NULL)return true;elsereturn false;
    }
    
  • 初始化——不带头结点

    //不带头结点初始化
    bool InitList(LinkList &L){L=NULL;return true;
    }//不带头结点判空
    bool Empty(LinkList L){if(L==NULL)return true;elsereturn false;
    }
    
  • 带头结点和不带头结点的区别

    • 头结点:不存储数据,只指向链表中第一个结点的位置

    • 不带头结点,写代码麻烦。原因:

      1.带头结点后,链表第一个位置上的结点与其他位置的操作可以一致,不用特殊处理。

      2.空表和非空表的处理得到统一。

3.1.2 单链表的插入
A.按位序插入(带头结点)
  • 将值为e的新结点插入到位置i,步骤:

    1.找到要插入的位置,即第i-1个结点;

    2.在其后插入新结点,插入步骤如图:

bool ListInsert(LinkList &L,int i,ElemType e){if(i<1)return false;LNode *p; //指针p指向当前扫描到的结点int j=0; //记录当前p指向第几个结点p=L; //初始时,L指向头结点,头结点不存数据//循环找到第i-1个结点,即要插入的位置while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL)return false;//i值不合法//插入结点LNode *s=(LNode*)malloc(sizeof(LNode)); //为要插入的结点开辟内存s->data=e; //将数值复值到新结点数据域s->next=p->next; //将新结点和后继结点连接p->next=s; //将新结点和前驱连接return true;
}
  • 时间复杂度: O ( n ) O(n) O(n)
B.按位序插入(不带头结点)
  • 在非第一个插入时,与带头结点相同。但插入第一位时不同,当在第一位插入时要重新赋值头结点。

  • 即在带头结点插入的基础上,插入以下一段即可:

bool ListInsert(LinkList &L,int i,ElemType e){if(i<1)return false;//插入第1个结点的操作与其它结点不同if(i==1){LNode *s=(LNode*)malloc(sizeof(LNode));s->data=e;s->next=L;L=s; //头指针指向新结点return true;}LNode *p; //指针p指向当前扫描到的结点int j=0; //记录当前p指向第几个结点p=L; //初始时,L指向头结点,头结点不存数据//循环找到第i-1个结点,即要插入的位置while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL)return false;//i值不合法//插入结点LNode *s=(LNode*)malloc(sizeof(LNode)); //为要插入的结点开辟内存s->data=e; //将数值复值到新结点数据域s->next=p->next; //将新结点和后继结点连接p->next=s; //将新结点和前驱连接return true;
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 后续不做特殊说明,则默认为带头结点。
C.指定结点的后插操作
  • 即在指定结点p后,插入元素e。

    相当于在按位序插入的基础上,省去循环查找第i-1个结点的步骤。

bool InsertNextNode(LNode *p,ElemType e){if(p==NULL)return false;LNode *s=(LNode*)malloc(sizeof(LNode));if(s==NULL)return false;s->data=e;s->next=p->next;p->next=s;return true;
}
  • 时间复杂度: O ( 1 ) O(1) O(1)
D.指定结点的前插操作
  • 方法一:

    传入头结点,遍历链表找到指定节点的前驱结点,再按后插的方式插入。

    • 时间复杂度: O ( n ) O(n) O(n)
  • 方法二: better!

    按后插的方式在指定结点后插入新结点,再交换指定节点和新结点的数值。

    • 时间复杂度: O ( 1 ) O(1) O(1)
    bool InsertPriorNode(LNode *p,ElemType e){if(p==NULL)return false;LNode *s=(LNode*)malloc(sizeof(LNode));if(s==NULL)return false;s->next=p->next;p->next=s; //连接s和p后s->data=p->data; //p数据复制到sp->data=e; //原s的数据给preturn true;
    }
    

    或者传入的是新结点,而不是数据时,也同理:

    bool InsertPriorNode(LNode *p,LNode *s){if(p==NULL||s==NULL)return false;s->next=p->next;p->next=s; //连接s和p后//交换值ElemType t=p->data;p->data=s->data;s->data=t;return true;
    }
    
3.1.3 单链表的删除
A.按位序删除
  • 删除第i个结点的步骤

    1.找到要插入位置的前驱结点,即第i-1个结点。(如图,q是要删结点)

    2.将要删除结点从链表中断开,即前驱结点的next指向要删结点的后驱结点。

    3.释放已删除的结点空间。

bool ListDelete(LinkList &L,int i,ElemType &e){if(i<1)return false;LNode *p;p=L; //p从头开始扫描int j=0; //当前p指向第几个结点while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL)return false; //i值不合法if(p->next==NULL)return false; //i-1后无结点LNode *q=p->next; //存储要删结点e=q->data; //e存储要删结点的值p->next=q->next; //将要删结点断开free(q);return true;
}
  • 时间复杂度: O ( n ) O(n) O(n)
B.删除指定结点
  • 方法:

    与指定结点的前插操作类似。

    1.交换指定结点和其后继结点的数据域;

    2.删除指定结点的后继结点。

    在这里插入图片描述

    • 时间复杂度: O ( 1 ) O(1) O(1)
bool DeleteNode(LNode*p){if(p=NULL)return false;LNode*q=p->next; //q指向指定结点p的后继p->data=p->next->data; //与后继结点交换数据p->next=q->next; //将q结点断开(q里存的是要删结点的数据)free(q);return true;
}
  • 注:

    若要删结点是最后一个结点,这样做有空指针的错误,只能用 从表头依次寻找p前驱的方法来删除。

3.1.4 单链表的查找
A.按位查找
  • 查找第i个元素

    从链表第一个开始往后循环查找。

    i是链表中元素下标。

LNode *GetElem(LinkList L,int i){if(i<0)return NULL;LNode *p=L;int j=0;while(p!=NULL&&j<i){p=p->next;j++;}return p;
}
  • 可以用于按位查找、删除中的封装:

B.按值查找
  • 找到数据域==e的结点

    时间复杂度: O ( n ) O(n) O(n)

LNode* LocateElem(LinkList L,ElemType e){LNode *p=L->next;while(p!=NULL&&p->data!=e)p=p->next;return p;
}
3.1.5 单链表的建立
A.尾插法
  • 步骤

    1.建立头结点(初始化);

    2.定义两个结点:一个指向表头结点s,另一个指向表尾结点r;

    3.循环输入结点值,并为新结点开辟空间;

    4.在表尾结点后插入新结点;

    5.更新表尾结点r,保证r永远指向最后一个结点;

    6.退出循环后,尾结点置空。

LinkList List_TailInsert(LinkList &L){int x;L=(LNode*)malloc(sizeof(LNode)); //创建头结点LNode *s,*r=L; //s始终指向表头结点,r指向表尾结点scanf("%d",&x);while(x!=9999){s=(LNode*)malloc(sizeof(LNode)); //创建新结点s->data=x;r->next=s; //将新结点插入r=s; //更新表尾结点的指针,保持r指向最后一个结点scanf("%d",&x);}r->next=NULL; //尾结点指针制空return L;
}
B.头插法
  • 注:

    头插法的输入和链表的数据是逆置关系:

LinkList List_HeadInsert(LinkList &L){LNode *s;int x;L=(LNode*)malloc(sizeof(LNode)); //创建头结点L->next=NULL; //初始化空链表scanf("%d",&x);while(x!=9999){s=(LNode*)malloc(sizeof(LNode)); //创建新结点s->data=x;s->next=L->next;L->next=s; //更新第一个结点scanf("%d",&x);}return L;
}
*完整代码 单链表带头结点
#include<stdio.h>
#include<stdlib.h>#define ElemType inttypedef struct LNode {ElemType data;struct LNode* next;
}LNode,*LinkList;//初始化
bool InitList(LinkList& L) {L = (LNode*)malloc(sizeof(LNode));L->next = NULL;return true;
}//求表长
int Length(LinkList L) {int len = 0;LNode* p = L;while (p->next != NULL) {len++;p = p->next;}return len;
}//头插法建立单链表
LinkList List_HeadInsert(LinkList& L) {L = (LNode*)malloc(sizeof(LNode));L->next = NULL;LNode* s;int x;scanf("%d", &x);while (x != 9999) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L->next;L->next = s;scanf("%d", &x);}return L;
}//尾插法建立单链表
LinkList List_TailInsert(LinkList& L) {int x;L = (LNode*)malloc(sizeof(LNode)); //创建头结点LNode* s, * r = L; //s指向头结点,r指向尾结点scanf("%d", &x);while (x != 9999) {s = (LNode*)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;scanf("%d", &x);}r->next = NULL;return L;
}//按序查找
LNode* GetItem(LinkList& L, int i) {LNode* p = L;int j = 0;while (j < i && p != NULL) {p = p->next;j++;}return p;
}//按值查找
int LocateElem(LinkList& L, ElemType e) {LNode* p = L;int j = 0;while (p != NULL && p->data != e) {p = p->next;j++;}return j;
}//按位序插入
bool ListInsert(LinkList& L, int i, ElemType e) {if (i < 0)return false;LNode* p = L;int j = 0;while (j < i-1 && p!= NULL) {p = p->next;j++;}if (p == NULL)return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true;
}//指定结点后插操作
bool InsertNextNode(LNode* p, ElemType e) {if (p == NULL)return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true;
}//指定结点前插操作
bool InsertPriorNode(LNode* p, ElemType e) {if (p == NULL )return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;
}//按位序删除
bool ListDelete(LinkList& L, int i, ElemType& e) {LNode* p = L;int j=0;while (j < i-1 && p != NULL) {p = p->next;j++;}if (p == NULL||p->next==NULL)return false;LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;
}//删除指定结点
bool DeleteNode(LNode* p) {if (p == NULL)return false;LNode* q = p->next;p->data = p->next->data;p->next = q->next;free(q);return true;
}void PrintList(LinkList& L) {LNode* p = L->next;while (p != NULL) {printf("%d ", p->data);p = p->next;}printf("\n\n");
}void DestroyList(LinkList& L) {LNode* p = L;while (L) {p = L;L = L->next;free(p);}
}int main() {LinkList L;printf("头插法建立单链表,输入以9999结束:\n");L=List_HeadInsert(L);PrintList(L);DestroyList(L);printf("尾插法建立单链表,输入以9999结束:\n");L=List_TailInsert(L);PrintList(L);printf("求表长:%d\n",Length(L));printf("\n");printf("按位序插入:\n");int pos=1, e=998;ListInsert(L, pos, e);PrintList(L);printf("指定结点的后插操作:\n");LNode* p =L->next;e = 222;InsertNextNode(p, e);PrintList(L);printf("指定结点的前插操作:\n");p = L->next;e = 111;InsertPriorNode(p, e);PrintList(L);printf("按值查找:\n");printf("查找222的位序是:%d\n", LocateElem(L, 222));printf("\n");printf("按序查找:\n");LNode* q = GetItem(L, 2);printf("查找第3个元素值是:%d\n", q->data);printf("\n");printf("按位序删除:\n");int ee;ListDelete(L, pos, ee);printf("删除的结点值:%d\n", ee);PrintList(L);printf("按指定结点删除:\n");p = L->next;DeleteNode(p);PrintList(L);
}

*完整代码 单链表不带头结点
#include<stdio.h>
#include<stdlib.h>#define ElemType inttypedef struct LNode {ElemType data;struct LNode* next;
}LNode, * LinkList;//初始化
bool InitList(LinkList& L) {L=NULL;return true;
}//求表长
int Length(LinkList L) {int len = 0;LNode* p = L;while (p!= NULL) {len++;p = p->next;}return len;
}//头插法建立单链表
LinkList List_HeadInsert(LinkList& L) {L= NULL;LNode* s;int x;//第一个结点要特殊判断scanf("%d", &x);L = (LNode*)malloc(sizeof(LNode));L->data = x;L->next = NULL;scanf("%d", &x);while (x != 9999) {s = (LNode*)malloc(sizeof(LNode));s->data = x;s->next = L;L = s;scanf("%d", &x);}return L;
}//尾插法建立单链表
LinkList List_TailInsert(LinkList& L) {int x;L = NULL;//第一个结点要特殊判断scanf("%d", &x);L = (LNode*)malloc(sizeof(LNode));L->data = x;L->next = NULL;LNode* s, * r = L; //s指向头结点,r指向尾结点scanf("%d", &x);while (x != 9999) {s = (LNode*)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;scanf("%d", &x);}r->next = NULL;return L;
}//按序查找
LNode* GetItem(LinkList& L, int i) {LNode* p = L;int j = 0;while (j < i && p != NULL) {p = p->next;j++;}return p;
}//按值查找
int LocateElem(LinkList& L, ElemType e) {LNode* p = L;int i = 0;while (p != NULL && p->data != e) {p = p->next;i++;}return i+1;
}//按位序插入
bool ListInsert(LinkList& L, int i, ElemType e) {if (i < 0)return false;//插入第1个结点的操作与其它结点不同if (i == 1) {LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = L;L = s; //头指针指向新结点return true;}LNode* p = L;int j = 0;while (j < i - 1 && p != NULL) {p = p->next;j++;}if (p == NULL)return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true;
}//指定结点后插操作
bool InsertNextNode(LNode* p, ElemType e) {if (p == NULL)return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true;
}//指定结点前插操作
bool InsertPriorNode(LNode* p, ElemType e) {if (p == NULL)return false;LNode* s = (LNode*)malloc(sizeof(LNode));s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;
}//按位序删除
bool ListDelete(LinkList& L, int i, ElemType& e) {if (i < 1)return false;//删除第1个结点的操作与其它结点不同if (i == 1) {e = L->data;LNode* s = L;L = L->next;free(s);return true;}LNode* p = L;int j = 0;while (j < i - 1 && p != NULL) {p = p->next;j++;}if (p == NULL || p->next == NULL)return false;LNode* q = p->next;e = q->data;p->next = q->next;free(q);return true;
}//删除指定结点
bool DeleteNode(LNode* p) {if (p == NULL)return false;LNode* q = p->next;p->data = p->next->data;p->next = q->next;free(q);return true;
}void PrintList(LinkList& L) {LNode* p = L;while (p != NULL) {printf("%d ", p->data);p = p->next;}printf("\n\n");
}void DestroyList(LinkList& L) {LNode* p = L;while (L) {p = L;L = L->next;free(p);}
}int main() {LinkList L;printf("头插法建立单链表,输入以9999结束:\n");L = List_HeadInsert(L);PrintList(L);DestroyList(L);printf("尾插法建立单链表,输入以9999结束:\n");L = List_TailInsert(L);PrintList(L);printf("求表长:%d\n", Length(L));printf("\n");printf("按位序插入:\n");int pos = 1, e = 998;ListInsert(L, pos, e);PrintList(L);printf("指定结点的后插操作:\n");LNode* p = L;e = 222;InsertNextNode(p, e);PrintList(L);printf("指定结点的前插操作:\n");p = L;e = 111;InsertPriorNode(p, e);PrintList(L);printf("按值查找:\n");printf("查找222的位序是:%d\n", LocateElem(L, 222));printf("\n");printf("按序查找:\n");LNode* q = GetItem(L, 2);printf("查找第3个元素值是:%d\n", q->data);printf("\n");printf("按位序删除:\n");int ee;ListDelete(L, pos, ee);printf("删除的结点值:%d\n", ee);PrintList(L);printf("按指定结点删除:\n");p = L;DeleteNode(p);PrintList(L);
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊云科技实时 AI 编程助手 Amazon CodeWhisperer,开发快人一步

​ ​ Amazon CodeWhisperer 是一款 AI 编码配套应用程序&#xff0c;可在 IDE 中生成 整行代码和完整的函数代码建议&#xff0c;以帮助您更快地完成更多工作。在本系列 文章中&#xff0c;我们将为您详细介绍 Amazon CodeWhisperer 的相关信息&#xff0c;敬请 关注&#xff…

代理IP安全问题:在国外使用代理IP是否安全

目录 前言 一、国外使用代理IP的安全风险 1. 数据泄露 2. 恶意软件 3. 网络攻击 4. 法律风险 二、保护国外使用代理IP的安全方法 1. 选择可信的代理服务器 2. 使用加密协议 3. 定期更新系统和软件 4. 注意网络安全意识 三、案例分析 总结 前言 在互联网时代&…

微信小程序固定头部-CSS实现

效果图 代码逻辑&#xff1a;设置头部的高度&#xff0c;浮动固定后&#xff0c;再加个这个高度的大小的外边距 .weui-navigation-bar {position: fixed;top: 0px;left: 0px;right: 0px;height:90px; } .weui-navigation-bar_bottom{height:90px; }

基于视觉识别的自动采摘机器人设计与实现

一、前言 1.1 项目介绍 【1】项目功能介绍 随着科技的进步和农业现代化的发展&#xff0c;农业生产效率与质量的提升成为重要的研究对象。其中&#xff0c;果蔬采摘环节在很大程度上影响着整个产业链的效益。传统的手工采摘方式不仅劳动强度大、效率低下&#xff0c;而且在劳…

Redis 协议与异步方式

redis pipeline 模式 redis pipeline 是一个客户端提供的机制&#xff0c;与 redis 无关。pipeline 不具备事务性。目的&#xff1a;节约网络传输时间。通过一次发送多条请求命令&#xff0c;从而减少网络传输时间。 时间窗口限流 系统限定某个用户的某个行为在指定的时间范围…

Laravel - API 项目适用的图片验证码

1. 安装 gregwar/captcha 图片验证码接口的流程是&#xff1a; 生成图片验证码 生成随机的 key&#xff0c;将验证码文本存入缓存。 返回随机的 key&#xff0c;以及验证码图片 # 不限于 laravel 普通 php 项目也可以使用额 $ composer require gregwar/captcha2. 开发接口 …

精品基于SpringBoot的体育馆场地预约赛事管理系统的设计与实现-选座

《[含文档PPT源码等]精品基于SpringBoot的体育馆管理系统的设计与实现[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#…

【Linux】实时查看服务器信息

查看服务器CPU使用率 使用命令mpstat 1。这里的1表示每隔1秒更新一次CPU使用率。如果系统未安装mpstat&#xff0c;可以通过安装sysstat包来获取它。 在基于Debian的系统&#xff08;如Ubuntu&#xff09;上&#xff0c;使用命令&#xff1a; sudo apt-get update sudo apt-…

刷题笔记 洛谷 P1162 填涂颜色

思路来自 大佬 hat.openai.com/c/9c30032e-5fb9-4677-8c15-9ea6530dc6db 题目链接 P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 搜索 首先 在外面围上一圈0开始搜素 因为题目说将封闭区域内的0变成2 我们可以在外面进行搜索 把外面所有可以搜索…

单片机烧录方式 -- IAP、ISP和ICP

目录 背景 1 什么是ICP 2 什么是ISP 3 什么是IAP 4 总结 背景 对于51单片机&#xff0c;我们使用STC-ISP上位机软件通过串口进行程序的烧写&#xff1b;对于STM32系列单片机&#xff0c;我们既可以通过串口烧写程序&#xff0c;也能通过JLink或是STLink进行程序的烧写&am…

ONLYOFFICE桌面编辑器v8.0完整指南:安装、特点与新增功能

文章目录 摘要引言安装主界面可填写的 PDF 表单双向文本支持电子表格中的新增功能其他改进与Moodle集成用密码保护PDF文件从“开始”菜单快速创建文档本地界面主题安装免费的 ONLYOFFICE桌面编辑器 总结 摘要 本文介绍了ONLYOFFICE桌面编辑器v8.0的安装、主界面特点以及新增功…

PID闭环控制算法的学习与简单使用

平台&#xff1a;matlab2021b&#xff0c;Vivado2018 应用场景和理解 一个早餐店&#xff0c;假如一天都有生意&#xff0c;生意有的时间很火爆&#xff0c;有时候又一般&#xff0c;老板又是个实在人&#xff0c;只知道在后厨蒸包子。由于包子蒸熟需要一定的时间&#xff0c;老…

面试数据库篇(mysql)- 12分库分表

拆分策略 垂直分库 垂直分库:以表为依据,根据业务将不同表拆分到不同库中。 特点: 按业务对数据分级管理、维护、监控、扩展在高并发下,提高磁盘IO和数据量连接数垂直分表:以字段为依据,根据字段属性将不同字段拆分到不同表中。 特点: 1,冷热数据分离 2,减少IO过渡争…

Qt中tableView控件的使用

tableView使用注意事项 tableView在使用时&#xff0c;从工具栏拖动到底层页面后&#xff0c;右键进行选择如下图所示&#xff1a; 此处需要注意的是&#xff0c;需要去修改属性&#xff0c;从UI上修改属性如下所示&#xff1a; 也可以通过代码修改属性&#xff1a; //将其设…

[项目]深度估计增强的多目标跟踪

去年10月开始到年底&#xff0c;做了一个小工作&#xff0c;就是将自监督单目深度估计与MOT结合&#xff0c;目的是充分利用深度信息解决遮挡问题&#xff0c;并且在估计深度的同时可以估计相机位姿&#xff0c;这是可以计算出相邻两帧像素的映射。这在视角较大变化下比较有用。…

OpenCV实现目标追踪

目录 准备工作 语言&#xff1a; 软件包&#xff1a; 效果演示 代码解读 &#xff08;1&#xff09;导入OpenCV库 &#xff08;2&#xff09;使用 cv2.VideoCapture 打开指定路径的视频文件 &#xff08;3&#xff09;使用 vid.read() 读取视频的第一帧&#xff0c;ret…

MyBatis 学习(一)之 MyBatis 概述

目录 1 MyBatis 介绍 2 MyBatis 的重要组件 3 MyBatis 执行流程 4 参考文档 1 MyBatis 介绍 MyBatis 是一个半自动化的 ORM &#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;持久层框架&#xff0c;它允许开发者通过 XML 或注解将对象与数据库中…

proteus8.15图文安装教程

proteus8.15版本可以用STM32系列单片机来进行仿真设计&#xff0c;比7.8版本方便多了&#xff0c;有需要的朋友们可以在公众号后台回复 proteus8.15 获取软件包。 1、下载好软件包&#xff0c;解压如下&#xff0c;右键proteus8.15.sp1以管理员身份运行。 2、第一次安装&#x…

获取tensorflow lite模型指定中间层的输出

以mobilenet v2为例子&#xff0c;我已经训练好了模型&#xff0c;有tflite格式和onnx格式两种模型的权重文件&#xff0c;我想获取tflite模型在推理阶段neck部分的输出。 查看onnx模型得到neck最后一层位置 使用netron查看onnx模型结构 从name中能知道Reshape是neck的最后一…

clickhouse 随心所欲的聚合模型-AggregatingMergeTree

clickhouse 强大的 MergeTree 系列引擎令人信服&#xff0c;其 ReplacingMergeTree、SummingMergeTree 在数据唯一性和汇总场景中表现非凡。但你是否还有保留最小(大)、平均等预聚合需求&#xff0c;甚至在一个模型中既有唯一性语意也有汇总、最小、最大、平均值语意该如何处理…