技术标签: # 数据结构 算法 理论通识基础 链表 指针 数据结构
/*不带头结点*/
typedef struct LNode { //定义单链表结点类型
ElemType data; //每个结点存放一个数据元素
struct LNode *next; //指针指向下一个结点
}LNode,*LinkList;
//初始化一个空的单链表
bool InitLink(LinkList &L) {
L = NULL; //空表,暂时没有任何结点
return true;
}
//判断单链表是否为空
bool Empty(LinkList L) {
if(L == NULL) {
return true;
}else {
return false;
}
}
void test01() {
LinkList L; //声明一个指向单链表的指针
InitLink(L); //初始一个空表
}
/*带头结点*/
typedef struct LNode { //定义单链表结点类型
ElemType data; //每个结点存放一个数据元素
struct LNode *next; //指针指向下一个结点
}LNode,*LinkList; //强调为结点和强调为单链表
//初始化一个空的单链表
bool InitLink(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;
}else {
return false;
}
}
void test02() {
LinkList L; //声明一个指向单链表的指针
InitLink(L); //初始一个空表
}
//在第i个位置插入元素e
/*带头结点*/
bool ListInsert(LinkList &L, int i, ElemType e) {
if(i < 1) {
return false;
}
//未封装
LNode *p; //指针P指向当前扫描到的结点
int j = 0; //当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL && j<i-1) { //循环找到第 i-1 个结点
p = p->next;
j ++;
}
//封装后
//LNode *p = GetElem(L, i-1); //找到第 i-1 个结点
//未封装
if(p == NULL) { //i值不合法
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next; //将结点s连到P之后
p->next = s; //插入成功
return true;
//封装后
//return InsertNextNode(p, e);
}
注意:进行插入时的指针指向顺序不可变,必须先执行s->next = p->next将插入结点与其插入后的后继结点相关联,再执行p->next = s将插入结点与其前驱结点相关联。若顺序颠倒,则会使新插入结点的next指针指向自己,而使插入位置之后的数据全部丢失。
//在第i个位置插入元素e
/*不带头结点*/
bool ListInsert(LinkList &L, int i, ElemType e) {
if(i < 1) {
return false;
}
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指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL && j<i-1) { //循环找到第 i-1 个结点
p = p->next;
j ++;
}
//未封装
if(p == NULL) { //i值不合法
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next; //将结点s连到P之后
p->next = s; //插入成功
return true;
//封装后
//return InsertNextNode(p, e);
}
结论:不带头结点写代码更加不方便,更建议使用带头结点的方式
//后插操作:在p结点之后插入元素e
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保存数据元素e
s->next = p->next;
p->next = s; //将结点s连接到p之后
return true;
}
//前插操作:在p结点之前插入元素e
bool InsertNextNode(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中元素复制到s中
p->data = e; //p中元素覆盖为e
return true;
}
bool ListDelete(LinkList &L, int i, ElemType e) {
if(i < 1) {
return false;
}
//未封装
LNode *p; //指针P指向当前扫描到的结点
int j = 0; //当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL && j<i-1) { //循环找到第 i-1 个结点
p = p->next;
j ++;
}
//封装后
//LNode *p = GetElem(L, i-1); //找到第 i-1 个结点
if(p == NULL) { //i值不合法
return false;
}
if(p->next == NULL) { //第 i-1 个结点之后已无其他结点
return false;
}
LNode *q = p->next; //令q指向被删除结点
e = q->data; //用e返回元素的值
p->next = q->next; //将*q结点从链中断开
free(q); //释放结点的存储空间
return true; //删除成功
}
//删除指定结点p
bool DeleteNode(LNode *p) {
if(p == NULL) { //i值不合法
return false;
}
LNode *q = p->next; //令q指向被删除结点
p->data = p->next->data;//和后继结点交换数据域
p->next = q->next; //将*q结点从链中断开
free(q); //释放结点的存储空间
return true; //删除成功
}
极限情况:若要删除的p恰好是最后一个结点,则方式二在执行到p->data = p->next->data会出现空指针错误,所以此方式不适用,只能使用方式一从表头开始依次寻找p的前驱可保证适用所有情况
LNode * GetElem(LinkList L, int i) {
if(i < 0) {
return false;
}
LNode *p; //指针P指向当前扫描到的结点
int j = 0; //当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL && j<i) { //循环找到第i个结点
p = p->next;
j ++;
}
return p;
}
LNode * LocatElem(LinkList L, ElemType e) {
LNode *p = L->next;
//从第1个结点开始查找数据域为e的结点
while(p!=NULL && p->data!=e) {
p = p->next;
}
return p; //找到后返回该结点指针,否则返回NULL
}
int Length(LinkList L) {
int len = 0; //统计表长
LNode *p = L;
while(p->next != NULL) {
p = p->next;
len ++;
}
return len;
}
文章浏览阅读2.1k次,点赞6次,收藏3次。1.什么是严苛模式(StrictMode) StrictMode是一个开发工具,检测到你可能的事情 偶然做的就让你的注意力,这样你就可以修复 他们。 StrictMode是最常用的磁盘或意外 网络访问应用程序的主线程,UI 操作和动画进行接收。 保持磁盘 和网络业务主线程会更为顺畅, 应用程序更加敏感。 通过保持应用程序的主线程 响应,你也阻止 ANR对话框 显示给用户。 注_谷歌调试模式严格模式
文章浏览阅读5.7k次。转自:https://zhidao.baidu.com/question/513526685.html修改它的上级文件夹权限,使该用户对这个文件夹只有读和运行的权限,就不能删除这个文件了。(也不能在这个文件夹新建文件)转自:https://blog.csdn.net/u014630623/article/details/51721032Linux设置文件夹可读写但是不能删除权限命令此..._linux 只给某个用户读写 其他只读不能删除
文章浏览阅读3.1w次,点赞11次,收藏84次。目录1. datediff('endTime',‘startTime’)2. date_sub(‘yyyy-MM-dd’,n/-m)3. date_add('yyyy-MM-dd',n/-m)ps:三个date函数日期均只能为'yyyy-MM-dd'格式 & 'yyyy-MM-dd HH:mm:s'格式1. datediff('endTime',‘startTime’)..._hive date_sub函数
文章浏览阅读9.6k次,点赞5次,收藏30次。一、子网掩码 IP地址是以网络号和主机号来标示网络上的主机的,我们把网络号相同的主机称之为本地网络,网络号不相同的主机称之为远程网络主机,本地网络中的主机可以直接相互通信;远程网络中的主机要相互通信必须通过本地网关(Gateway)来传递转发数据。 1、子网掩码的概念及作用 ①、子网掩码(Subnet Mask)又叫网络掩码、地址掩码,必须结合IP地址一起对应使用。 ②、只有通过子..._子网掩码怎么用
文章浏览阅读2.2k次,点赞2次,收藏3次。订阅发布模式是一种特殊的生产消费者模式区别:1.消息是否被多个对象处理。生产消费者是所有消费者抢占消息,订阅发布是所有订阅者共享消息。2.主动权不同。生产消费者主动权在消费者,订阅发布主动权在发布者。也就说订阅者是把主动权交给了发布者,从代码层面更好的实现解耦。..._生产消费模式和发布订阅模式的区别
文章浏览阅读959次。【数字IC前端笔试真题精刷(2022.7.7)】燧原——AI芯片验证工程师_燧原科技ai芯片和系统验证工程师(硬件方向)/gpu 功耗与性能优化笔试
文章浏览阅读331次。1.什么是vue-clivue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程。2.安装和使用vue-ci(1)vue-cli 是 npm 上的一个全局包,使用 npm install 命令,即可方便的把它安装到自己的电脑上:npm install -g @vue/cl(2)基于vue-ci快速生成工程化的vue项目:vue create 项目的名称(3)vue-cli创建项目的步骤截图:1)选择第三个,表示_vue-cli 运行
文章浏览阅读2.4k次。1. MotivationDeTR [3] examines the idea of global optimal matching. But the Hungarian algo- rithm they adopted can only work in a one-to-one assign- ment manner.One-to-Many 的方法。So far, for the CNN based detectors in one-to-many scenarios, a global ._ot problem
文章浏览阅读365次,点赞3次,收藏5次。Blendid: 现代化的Gulp工作流解决方案项目地址:https://gitcode.com/vigetlabs/blendidBlendid 是一个由Viget Labs开发的开源项目,它是一个基于Gulp的自动化构建工具,专为简化前端开发流程而设计。项目的目标是将复杂的前端构建任务转变为简单、直观且高效的体验,让开发者更专注于编写代码,而非配置构建系统。技术分析Blendid 使用...
文章浏览阅读3.1k次。#-*- coding: utf-8 -*-"""按扭操作"""import Tkinterclass Application(Tkinter.Frame): count = 0 def __init__(self, master=None): Tkinter.Frame.__init__(self, master)_x *= self.scale_
文章浏览阅读2.2k次。又看到有人把数据放在data中也有发现有人把数据放在params中,他们有什么区别和关系呢?这里只讨论GET和POST两种情况下,而且过程中只做基于现象的推测。实验环境:Django作为后端查看请求本着基于求成的想法,直接进行实验比较数据和请求准备import request from 'umi-request';const options = { params:{p:"param"}, data:{d:"data"} }const url = "yo_uni.request params
文章浏览阅读3.8k次,点赞14次,收藏42次。从新手码农到高级架构师,要经过几步?要多努力,才能成为为人倚重的技术专家?本文将为你带来一张程序员发展路径图,但你需要知道的是,天下没有普适的道理,具体问题还需具体分析,实践才能出真知。架构师的“内功”我认为,架构师的内功主要包含三部分:判断力、执行力、创新力,简单解释如下:判断力:能够准确判断系统的复杂度在哪里,就像武侠高手一样,能准确地看出对手的破绽和弱点。执行力:能够使用合适的方案解决复杂度问题,就像武侠高手一样,能选择合适的招式或者方法打败对手。创新力:能够创造新的解决方案..._突破java瓶颈