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

佛科院计算机软件技术基础——线性表

一、基础知识了解:

  1. 结构体的理解:

我们知道整型是由1位符号位和15位数值位组成,而就可以把结构体理解为我们定义的数据类型,如:

typedef struct
{int data[2];        //存储顺序表中的元素int len;                        //顺序表的表长
}SeqList;                             //顺序表类型

在这个结构体中我们定义前2*16位存放顺序表中的数据,最后1*16位存放表长

对于:

SeqList List;

这个就是类似于整型的一个结构体类型的变量,我们可以通过(List.len/List.data[i])调用结构体变量中的元素。

对于:

SeqList *L;//等同于int *L;,只不过可指向的数据类型不同

不过跟int *L;相同的,定义只是一个空指针,需要通过申请一段内存空间才能使用:

L=(SeqList*)malloc(sizeof(SeqList));
  1. 结构体变量的地址:

结构体变量的地址为首个成员的地址

  1. 指针的理解:

指针是一种通过指向地址来操纵数据的方式

如:

typedef struct
{//MAXSIZE是根据实际问题所定义的一个足够大的整数//datatype为顺序表中元素的类型,在具体实现中可为int、float、char类型或其他结构类型datatype data[MAXSIZE];        //存储顺序表中的元素int len;                        //顺序表的表长
}SeqList;                             //顺序表类型//构造一个空表
SeqList *Init_SeqList()
{SeqList *L;//建立一个SeqList类型的空指针L=(SeqList*)malloc(sizeof(SeqList));//申请空间,并让L指向该空间的地址L->len=0; //顺序表的表长为0return L;
}
  1. 对SeqList **L的理解:

对于:

typedef struct node
{datatype data;            //data为结点的数据信息struct node *next;      //与SeqList *L;类似,存放了另一个LNode结构体变量的首地址
}LNode;                                  

我们可以重点看struct node *next; ,如果我们要操作next地址对应结构体的数据data,我们就要用到SeqList **L

如:

一、顺序表

  1. 顺序表定义:

typedef struct
{//datatype为表中元素类型(int,float等)//元素存放在data数组中//MAXSIZE是根据实际问题所定义的一个足够大的整数datatype data[MAXSISE];int len;//表长
}SeqList;
  1. 指向顺序表的指针变量

SeqList list,*L;
//list是结构体变量,它内部含有一个可存储顺序表的data数组
//L是指向List这类结构体变量的指针变量

其中:

(1)List.data[i]或L->data[i]均表示顺序表中第i个元素的值

(2)List.len或L->len均表示顺序表的表长

(3)“L=(SeqList*)malloc(sizeof(SeqList));”表示生成一个顺序表存储空间

  1. 顺序表的初始化

typdefine struct 
{datatype data[MAXSIZE];int len;
}Seqlist;
Seqlist *seqlist_Init()
{Seqlist *l;l = (Seqlist*)malloc(sizeof(Seqlist));l->len = 0;return l;
}
  1. 建立顺序表:(没搞懂)

(1)头部插入

先读取需要输入数据个数,再进行读取外部数据操作,最后将数据按顺序存放到顺序表中的数组

void CreatList(SeqList **L)
{int i, n;printf("Input length of List: ");scanf("%d", &n);printf("Input elements of List: \n");for(i=1;i<=n;i++)scanf("%d", &(*L)->data[i]);(*L)->len=n;
}

(2)尾部插入

LNode *CreateLinkList()
{LNode *head, *p, *q; char x;head=(LNode*)malloc(sizeof(LNode));       //生成头结点head->next=NULL;p=head; q=p;                                    //指针q始终指向链尾结点printf("Input any char string: \n");scanf("%c", &x);while(x!='\n')                                  //生成链表的其他结点{p=(LNode*)malloc(sizeof(LNode));p->data=x;p->next=NULL;q->next=p;                                    //在链尾插入q=p;scanf("%c", &x);}return head;                                   //返回单链表表头指针
}
  1. 插入运算:

先判断表是否满了和插入位置是否合理,再将i到len个从后面到前面逐个向后移,最后再插入到第i个位置

void Insert_SeqList(SeqList *L, int i, datatype x)
{int j;if(L->len==MAXSIZE-1)                   //表满printf("The List is full!\n");elseif(i<1|| i>L->len+1)                //插入位置非法printf("The position is invalid !\n");else{for(j=L->len;j>=i;j--)          //将an~ai顺序后移一个元素位置L->data[j+1]=L->data[j];L->data[i]=x;                   //插入x到第i个位置L->len++;                          //表长增1}
}}
  1. 删除运算:

void Del_LinkList(LNode *head , int i)
{                     //删除单链表head上的第i个数据结点LNode *p, *q;p=Get_LinkList(head, i-1);               //查找第i-1个结点if(p==NULL)printf("第i-1个结点不存在!\n "); //待删结点的前一个结点不存在,无待删结点elseif(p->next==NULL)printf("第i个结点不存在!\n");        //待删结点不存在else{q=p->next;                //q指向第i个结点p->next=q->next;            //从链表中删除第i个结点free(q);                //系统回收第i个结点的存储空间}
}
  1. 查找:

给值查找存储位置:以该一位元素是否为x和该位是否在在顺序表中为判断条件,最后如果跳出时的元素为x则返回i,不是则返回0

int Location_SeqList(SeqList *L, datatype x)
{int i=1;                                  //从第一个元素开始查找while(i<L->len&&L->data[i]!=x)//顺序表未查完且当前元素不是要找的元素i++;if(L->data[i]==x)return i;                                //找到则返回其位置值elsereturn 0;                                              //未找到则返回0值
}

二、单链表

  1. 单链表结点定义:

只需要定义一个存放数据和后一个节点地址的结构体就行


typedef struct node
{datatype data;            //data为结点的数据信息struct node *next;      //next为指向后继结点的指针
}LNode;                                  //单链表结点类型
  1. 建立单链表:

首先建立一个任意的头节点,读取外部输入数据,

void CreateLinkList(LNode **head)
{                       //将主调函数中指向待生成单链表的指针地址(如&p)传给**headchar x;LNode *p;*head=(LNode *)malloc(sizeof(LNode)); //在主调函数空间生成链表头结点(*head)->next=NULL;        //*head为链表头指针printf("Input any char string: \n");scanf("%c", &x);      //结点的数据域为char型,读入结点数据while(x!='\n')             //生成链表的其他结点{p=(LNode *)malloc(sizeof(LNode));     //申请一个结点空间p->data=x;p->next=(*head)->next;       //将头结点的next值赋给新结点*p的next(*head)->next=p;    //头结点的next指针指向新结点*p实现在表头插入scanf("%c", &x);            //继续生成下一个新结点}

(1)为什么使用LNode **head?(未解决)

由于我们要与主函数联系起来,必须确定头节点的

  1. 查找:

(1)按序号:

根据指针域一直寻址到第i个结点,以循环次数与最后一个节点为结束标志

LNode *Get_LinkList(LNode *head, int i)
{                                 //在单链表head中查找第i个结点LNode *p=head;              //由第一个结点开始查找int j=0;while(p!=NULL&&j<i)         //当未查到链尾且j小于i时继续查找{p=p->next;j++;}return p;           //找到则返回指向i结点的指针值,找不到则p返回空值
}

(2)按值查找:

根据指针域一直寻址,以找到目标值和最后一个数为结束标志

LNode *Locate_LinkList(LNode *head, char x)
{                                //在单链表中查找结点值为x的结点LNode *p=head->next;     //由第一个数据结点开始查找while(p!=NULL&&p->data!=x) //当未查到链尾且当前结点不等于x时继续查找p=p->next;return p; //找到则返回指向值为x的结点的指针值,找不到则p返回空值
}
  1. 求表长:

从第一个结点寻址到最后一个结点,并做计数

int Length_LinkList(LNode *head)
{LNode *p=head;                //p指向单链表头结点int i=0;                         //i为结点计数器while(p->next!=NULL){p=p->next;i++;}return i;                       //返回表长值i
}
  1. 插入:

利用查找函数获得第i-1个结点的地址,如果该结点地址为空(即最后一个结点),说明插入操作非法;如果不为空,创建一个新节点数据域存放插入数据,指针域域存放下一个结点的地址,上一个结点的指针域放新节点的地址

void Insert_LinkList(LNode *head, int i, char x)
{                                               //在单链表head的第i个位置上插入值为x的元素LNode *p, *q;p=Get_LinkList(head, i-1);            //查找第i-1个结点*/if(p==NULL) printf("Error ! \n");                 //第i-1个位置不存在而无法插入else{q=(LNode *)malloc(sizeof(LNode));    //申请结点空间q->data=x;q->next=p->next;                      //完成插入操作①p->next=q;                             //完成插入操作②}
}
  1. 删除:

首先像插入操作一样判断删除操作是否非法,如果合法,则让第i-1个结点的地址域直接存放第i+1个结点的地址,同时把第i个结点的空间释放

算法如下:
void Del_LinkList(LNode *head , int i)
{                     //删除单链表head上的第i个数据结点LNode *p, *q;p=Get_LinkList(head, i-1);               //查找第i-1个结点if(p==NULL)printf("第i-1个结点不存在!\n "); //待删结点的前一个结点不存在,无待删结点elseif(p->next==NULL)printf("第i个结点不存在!\n");        //待删结点不存在else{q=p->next;                //q指向第i个结点p->next=q->next;            //从链表中删除第i个结点free(q);                //系统回收第i个结点的存储空间}
}

三、循环链表

  1. 查找循环链表中某个数:

与单链表类似,只不过最后的一个查找的地址不是NULL而是头节点

LNode *Locate_CycLink(LNode *head, datatype x)
{LNode *p=head->next;       //由第一个数据结点开始查while(p!=head&&p->data!=x)//未查完循环链表且当前结点不等于x时继续查找p=p->next;if(p!=head)                       //head   代表结束点return p;              //找到值等于x的结点*p,返回其指针值pelsereturn NULL; //当p又查到头结点时则无等于x值的结点,故返回NULL值
}

四、单链表应用

例1:

通过两个指针将

void Convert(LNode *H)
{LNode *p, *q;p=H->next;               //p指向剩余结点链表的第一个数据结点H->next=NULL;               //新链表H初始为空while(p!=NULL){q=p;                   //从剩余结点链表中取出第一个结点p=p->next;             //p继续指向剩余结点链表新的第一个数据结点q->next=H->next;     //将取出的结点*q插入新链表H的链首H->next=q;}
}

例2:

首先把A的头节点赋给C,释放B的头节点,再将A、B中较小的用头插法赋给C,再该链表推进到下一个结点,循环该操作直到A,B中任意一方到最后一个结点,最后将剩余元素用头插法赋给C

 void Merge(LNode *A, LNode *B, LNode **C)
{                           //将增序链表A、B合并成降序链表*CLNode *p, *q, *s;p=A->next;              //p始终指向链表A的第一个未比较的数据结点q=B->next;               //q始终指向链表B的第一个未比较的数据结点*C=A;                     //生成链表的*C的头结点(*C)->next=NULL;free(B);                 //回收链表B的头结点空间while(p!=NULL&&q!=NULL){   //将A、B两链表中当前比较结点中值小者赋给*sif(p->data<q->data){s=p;   p=p->next;}else{s=q; q=q->next;}s->next=(*C)->next; //用头插法将结点*s插到链表*C的头结点之后(*C)->next=s;}if(p==NULL)    //如果指向链表A的指针*p为空,则使*p指向链表Bp=q;while(p!=NULL){//将*p所指链表中的剩余结点依次摘下插入链表*C的链首s=p;p=p->next;s->next=(*C)->next;   (*C)->next=s;}

例3:

首先建立一个单链表,再将最后一个地址域赋上头节点地址形成循环列表,

void Josephus(int n, int m, int k)
{LNode *p, *q;int i;p=(LNode*)malloc(sizeof(LNode));q=p;for(i=1;i<n;i++)     //从编号k开始建立一个单链表{q->data=k;k=k%n+1;q->next=(LNode*)malloc(sizeof(LNode));q=q->next;}q->data=k; q->next=p;              //链接成循环单链表,此时p指向编号为k的结点while(p->next!=p)       //当循环单链表中的结点个数不为1时{for(i=1;i<m;i++){q=p;  p=p->next;}                          //p指向报数为m的结点,q指向报数为m-1的结点q->next=p->next;              //删除报数为m的结点printf("%4d", p->data);       //输出出圈人的编号free(p);                      //释放被删结点的空间p=q->next;                    //p指向新的开始报数结点}printf("%4d", p->data);         //输出最后出圈人的编号
}

相关文章:

佛科院计算机软件技术基础——线性表

一、基础知识了解&#xff1a;结构体的理解&#xff1a;我们知道整型是由1位符号位和15位数值位组成&#xff0c;而就可以把结构体理解为我们定义的数据类型&#xff0c;如&#xff1a;typedef struct {int data[2]; //存储顺序表中的元素int len; …...

linux下终端操作mysql数据库

目录 一&#xff0e;检查mysql是否安装 1. 查看文件安装路径 2. 查询运行文件所在路径(文件夹地址) 二&#xff0e;登录mysql 三&#xff0e;列出mysql全部用户 四&#xff0e;常用指令 &#xff11;&#xff0e;查看全部数据库 &#xff12;&#xff0e;选择数据库 …...

MySQL参数优化之thread_cache_size

1.thread_cache_size简介 每建立一个连接&#xff0c;都需要一个线程来与之匹配&#xff0c;此参数用来缓存空闲的线程&#xff0c;以至不被销毁&#xff0c;如果线程缓存中有空闲线程&#xff0c;这时候如果建立新连接&#xff0c;MYSQL就会很快的响应连接请求。 show statu…...

gRPC服务健康检查(二):gRPC健康检查协议详解

gRPC健康检查协议健康检查用于检测服务端能否正常处理rpc请求&#xff0c;客户端对服务端的健康检查可以点对点进行&#xff0c;也可以通过某些控制系统&#xff08;如负载平衡&#xff09;进行。客户端可以根据服务端返回的状态执行对应的策略。因为GRPC服务可以用于简单的客户…...

Android系统10 RK3399 init进程启动(四十七) Android init 进程整体代码逻辑简述

配套系列教学视频链接&#xff1a;安卓系列教程之ROM系统开发-百问100ask说明系统&#xff1a;Android10.0设备&#xff1a; FireFly RK3399 &#xff08;ROC-RK3399-PC-PLUS&#xff09;前言本文简单描述一下android init祖先进程启动的基本执行流程&#xff0c;让大家有一个整…...

CSDN 编程竞赛三十二期题解

竞赛总览 CSDN 编程竞赛三十二期&#xff1a;比赛详情 (csdn.net) 竞赛题解 题目1、传奇霸业 传奇霸业&#xff0c;是兄弟就来干。小春&#xff08;HP为a&#xff09;遇到了一只黄金哥布林&#xff08;HP为x&#xff09;。小春每次能对哥布林造成b点伤害&#xff0c;哥布林…...

Kubernetes 中的 Pod Hook

Pod Hook 我们知道Pod是Kubernetes集群中的最小单元&#xff0c;而 Pod 是有容器组组成的&#xff0c;所以在讨论 Pod 的生命周期的时候我们可以先来讨论下容器的生命周期。 实际上 Kubernetes 为我们的容器提供了生命周期钩子的&#xff0c;就是我们说的Pod Hook&#xff0c…...

Linux操作系统安装MySQL(rpm安装)

Linux操作系统安装MySQL&#xff08;rpm安装&#xff09;1 背景2 环境说明3 准备工作3.1 端口查看3.2 检查安装3.3 创建MySQL用户和组4 MySQL安装4.1 下载MySQL4.2 解压安装包4.3 安装MySQL4.4 初始化MySQL4.5 启动MySQL4.6 设置MySQL初始密码4.6.1 查看数据库初始密码4.6.2 更…...

MySQL高级第二讲

目录 二、MySQL高级02 2.1 触发器 2.1.1 触发器介绍 2.1.2 创建触发器 2.2 MySQL的体系结构 2.3 存储引擎 2.3.1 存储引擎概述 2.3.2 各种存储引擎特性 2.3.3 InnoDB 2.3.4 MyISAM 2.3.5 MEMORY 2.3.6 MERGE 2.3.7 存储引擎的选择 2.4 优化sql 2.4.1 查看sql执行…...

凸优化专题1

多变量函数的求导与求梯度/矩阵求导 1. 导数 定义: 设f:Rn→Rm,且x∈intdomf,则f在点x的导数(或称Jacobian)记为矩阵Df(x)∈Rmnf:\R^n \rightarrow \R^m, 且x\in \mathbf{int}\ \mathbf{dom} f, 则f 在点x的导\\数(或称Jacobian)记为矩阵 Df(x) \in \R^{m\times n}f:Rn→Rm,且…...

【蓝桥杯每日一题】递推算法

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; 蓝桥杯 &#x1f319;我与杀戮之中绽放&#xff0c;亦如黎明的花…...

Unity性能优化: 性能优化之内存篇

前言 本文和传统的内存优化不一样&#xff0c;不是讲如何降低内存占用&#xff0c;而是讲编程开发中要注意的内存问题以及一些内存技术的演变与原理。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验呀 1: Application进程…...

华为OD机试题,用 Java 解【内存资源分配】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

微服务之Nacos注册与配置

&#x1f3e0;个人主页&#xff1a;阿杰的博客 &#x1f4aa;个人简介&#xff1a;大家好&#xff0c;我是阿杰&#xff0c;一个正在努力让自己变得更好的男人&#x1f468; 目前状况&#x1f389;&#xff1a;24届毕业生&#xff0c;奋斗在找实习的路上&#x1f31f; &#x1…...

Android 动画详解

Android动画的分类与使用学习Android必不可少的就是动画的使用了&#xff0c;在Android版本迭代的过程中&#xff0c;出现了很多动画框架&#xff0c;这里做一个总结。Android动画类型分类逐帧动画【Frame Animation】&#xff0c;即顺序播放事先准备的图片。补间动画【Tween A…...

Linux -- 程序 进程 线程 概念引入

程序与进程 &#xff1a;程序 &#xff1a;什么是程序 &#xff1f;&#xff1f;&#xff1f;伪官方 &#xff1a; 二进制文件&#xff0c;文件存储在磁盘中&#xff0c;例如 /usr/bin 目录下 。 是静态。 简单讲 &#xff1a;# 我们都学习了语言&#xff0c;比如下面这串代…...

Android ART dex2oat

一、什么是dex2oat Dex2oat (dalvik excutable file to optimized art file) &#xff0c;是一个对 dex 文件进行编译优化的程序&#xff0c;在我们的 Android 手机中的位置是 /system/bin/dex2oat&#xff0c;对应的源码路径为 android/art/dex2oat/dex2oat.cc&#xff0c;通…...

「RISC-V Arch」RISC-V 规范结构

日期&#xff1a;20230228 规范分类 根据 RISC-V 设计哲学&#xff0c;其规范文档也是高度模块化的&#xff1a; ISA 规范&#xff08;2 篇&#xff09; 非特权规范特权规范 非 ISA 规范&#xff08;6篇&#xff09; Trace规范ABI 规范外部调试规范PLIC 规范SBI 规范UEFI 协…...

【C】线程控制

创建线程 #include <pthread.h>int pthread_create(pthread_t * thread,const pthread_attr_t * attr,void *(*start_routine)(void*), void * arg);返回值&#xff1a;成功返回0&#xff0c;失败返回错误号。 thread&#xff1a;成功返回后&#xff0c;新创建的线程的…...

Maven工程打jar包的N种方式

Maven工程打jar包 一、IDEA自带打包插件二、maven插件打包2.1 制作瘦包&#xff08;直接打包&#xff0c;不打包依赖包&#xff09;2.2 制作瘦包和依赖包&#xff08;相互分离&#xff09;2.3 制作胖包&#xff08;项目依赖包和项目打为一个包&#xff09;2.4 制作胖包&#xf…...

智能客服体验问题诊断:从技术架构到优化实践

智能客服体验问题诊断&#xff1a;从技术架构到优化实践 智能客服作为企业与用户交互的重要窗口&#xff0c;其体验好坏直接影响用户满意度和业务转化率。一个响应迟钝、答非所问的客服机器人&#xff0c;不仅无法解决问题&#xff0c;反而会加剧用户的不满。本文将从一个开发者…...

DeepSeek-OCR 2技术突破:动态视觉token重排效果展示

DeepSeek-OCR 2技术突破&#xff1a;动态视觉token重排效果展示 1. 引言 想象一下&#xff0c;当你阅读一份复杂的学术论文时&#xff0c;眼睛不会机械地从左上角扫到右下角&#xff0c;而是会自然地跳过标题、关注图表、追踪公式推导&#xff0c;甚至在不同的文本栏之间灵活…...

OpenClaw 小龙虾Windows10 专属一键部署教程|10 分钟搞定本地 AI 数字员工

适配系统&#xff1a;Windows10 64 位&#xff08;纯小白友好版&#xff09; 核心优势&#xff1a;免命令行、免环境配置、解压即装&#xff0c;内置所有运行依赖&#xff0c;全程可视化操作&#xff0c;新手也能一次成功部署 2026 爆火的开源 AI 智能体&#xff01; 本文专属…...

3大核心模块:Steam成就管理开源工具从问题解决到效率提升的实战指南

3大核心模块&#xff1a;Steam成就管理开源工具从问题解决到效率提升的实战指南 【免费下载链接】SteamAchievementManager A manager for game achievements in Steam. 项目地址: https://gitcode.com/gh_mirrors/st/SteamAchievementManager 引言 在游戏玩家的日常体…...

PT插件配置完全指南:从基础到进阶的全方位解决方案

PT插件配置完全指南&#xff1a;从基础到进阶的全方位解决方案 【免费下载链接】PT-Plugin-Plus PT 助手 Plus&#xff0c;为 Microsoft Edge、Google Chrome、Firefox 浏览器插件&#xff08;Web Extensions&#xff09;&#xff0c;主要用于辅助下载 PT 站的种子。 项目地址…...

滚动轴承动力学模型代码复现及三维模型SolidWorks文件分享

滚动轴承动力学模型代码 #指定了某篇paper复现&#xff0c;具体都如图打包在文件夹了&#xff0c;保证程序可以打开。 给出轴承三维模型solidworks软件打开2019版本可以打开。打开SolidWorks轴承模型时&#xff0c;金属滚珠与保持架的精密配合让人想起小时候拆解机械闹钟的经历…...

别再死记硬背了!动态规划解回文问题的填表顺序与状态定义保姆级图解

动态规划解回文问题&#xff1a;从填表顺序到状态定义的思维重塑 第一次接触回文串的动态规划解法时&#xff0c;我盯着那个双重循环的填表顺序发呆了半小时——为什么i要从n-1开始倒着遍历&#xff1f;为什么j又要从i开始正着遍历&#xff1f;更让我困惑的是&#xff0c;dp[i…...

背包问题可视化:用动态规划表格理解0-1背包最优解

背包问题可视化&#xff1a;用动态规划表格理解0-1背包最优解 当你第一次面对背包问题时&#xff0c;可能会被那些复杂的公式和递归关系搞得晕头转向。我们常常会遇到这样的情况&#xff1a;明明看懂了算法描述&#xff0c;但一到手动计算就不知所措。这就是为什么我们需要一种…...

长上下文不可强求:从 Gemini 到 Opus,1M context 为什么还没体现出应有价值

长上下文不可强求&#xff1a;从 Gemini 到 Opus&#xff0c;1M context 为什么还没体现出应有价值 摘要 过去一年&#xff0c;long context 一直是大模型产品最容易被拿来宣传的能力之一。32K 不够&#xff0c;就上 128K&#xff1b;128K 还不够&#xff0c;就上 1M。看起来&a…...

LabelMe企业级部署方案:多用户权限管理与审计

LabelMe企业级部署方案&#xff1a;多用户权限管理与审计 LabelMe是一款强大的图像标注工具&#xff0c;支持多边形、矩形、圆形等多种标注形式&#xff0c;广泛应用于计算机视觉领域的数据准备工作。在企业环境中部署LabelMe时&#xff0c;多用户权限管理与操作审计是确保数据…...