n1.线性表及其实现

1.引入—多项式表示

对于多项式,如何使用程序进行编写呢?
在这里插入图片描述
方法一:一维数组。下标对应未知数的指数,元素个体对应系数。缺点就是都得全部表示,系数为0项的存在浪费空间。例如,x只有一次方和2000次方,那么必须建立一个a[2001]这样大的数组才能进行多项式的编写。
方法二:二维数组。一维数组中存在一维数组{{1,5},{4,8},{5,3}},这样保证了系数为0的项不占用空间,根本不用写入二维数组中去。
方法三:链表。链表中的data部分包括x的指数以及所对应的系数,最后由link部分链接到下一指数。

如何进行多项式之间的运算呢?
比如两多项式F1 和 F2之间进行加法运算,首先将两个多项式按照指数递减进行排序。从F1的第一项开始,开始和F2的第一项进行比较。指数大的先输出,指数小的继续和另一多项式的下一项进行比较。如果指数相等,那么系数相加再输出。

2.线性表的顺序储存

在这里插入图片描述

  • 线性表应该具有的一些功能:

在这里插入图片描述

  • 使用顺序结构(即数组)的方式实现线性表

创建结构

#include <stdio.h>
#include <stdlib.h>
struct LNode{int Data[maxsize];//数据类型随便int last;//表示的是做后一个元素的下标
};
typedef struct LNode* List;
struct LNode L;
List PtrL;
//访问下标为i的元素:
L.Data[i];/ PtrL->Data[i];
//线性表的长度:
L.last + 1 / PtrL->last +1

初始化—建立空的线性表

List MakeEmpty()
{List PtrL;//表明Ptrl是指向结构类型的指针L = (List)malloc(sizeof(struct LNode));//分配内存用于储存数据。L->last = -1;//若数组中存在一个元素,这个元素的下标就是0,last = 0;若线性表为空,表示数组中没有元素,那么last = -1.
}

查找

int Find(int X,List PtrL)//传入要查找的元素(注意数据类型要和数组的一致)和指向线性表结构的指针,因为使用循环会用到数组的大小
{int result = -1;for(int i = 0,i < (PtrL->last + 1/*数组的长度*/),i++){if(PtrL->Data[i] == X){result = i;break;}}return result;
}

插入

想要实现在数组Data[]第i个位置上插入元素X,即对应的下标为Data[i-1]。那么首先要做的事情就是将第i个位置及其之后的元素全部向后挪动一位,再进行插入的操作。

void Insert(int i/*要插入的位置*/,int X/*要插入的元素*/,List PtrL)
{if(PtrL->last + 1 == maxsize)printf("不好意思,表已经满了,不可进行插入操作");else if(i <= 0 || i>=maxsize)printf("请输入有效的位置!");for(int j = Ptrl->last;j>= i-1;j--){PtrL->Data[j+1] = PtrL->Data[j];//注意要 从后向前 逐次后退一格}PtrL->Data[i-1] = X;//下标为i-1的就是第i个元素PtrL->last++;//因为实现了元素的插入,最后一个元素下标要+1
}

如果表没有满,那么我们不确定到底空出了几个位置,但是PtrL->last告诉了我们最后一个元素的准确位置,直接使用last即可,即从最后一个元素开始向后挪动。

删除

对数组中第i个位置元素进行删除,那么之后数组中第i个位置就空出来了,之后需要对i之后的所有元素进行向前挪动一位。

void Delete(int i;List PtrL)
{if(i <= 0 || i > PtrL->last+1)printf("请输入有效的位置!");for(int j = i-1/*第i个元素要被填上*/;j <= PtrL->last;j++){PtrL->Data[j] = PtrL->Data[j+1];//注意从前向后依次向前挪动}PtrL->last--;
}

2.线性表的链式储存

使用顺序储存的时候,因为数组中的元素在内存中是连续的,所以每当对线性表进行操作的时候,往往会进元素的挪动。而使用链结构,只要轻易地修改链就行了,不需要对元素进行挪动
--------关于指向结构类型的指针P的理解:P指向了一个结构体,里面包含data部分和Next部分,P = P->Next就实现了指针之间的赋值,其实P还是指针。那么就可以将P理解为一个结构体?P既指向了data部分又指向了Next部分。

创建结构

typedef struct LNode* List;
struct LNode{int data;List Next;
};
List PrtL = malloc(sizeof(struct LNode));

求表长

int Length(List PtrL/*传入的是表头*/)
{int count = 0 ;List p = PrtL;while(p->Next != NULL){count++;p = p->Next;}return count++;
}

查找

寻找data=X的结点的位置:
int Find(int X,List PtrL)
{List P = PtrL;int locate = 1;while(P->data != X && P->Next != NULL)//条件对应两种情况。如果最后P->data=X,那么无论P此时是不是表尾,都要返回locate;else就是找遍了链表就是没找到。{P= P->Next;locate++;}int result = -1;if(P->data == X){result = locate;}return locate;
}
寻找第K个节点
List FindKth(int K;List PtrL)
{List P = PtrL;int order = 1;while(P->Next != NULL){P = P->Next;order++:if(order == K )break;}return P;
}

插入

在第i-1的节点后面(也就是第i个节点)插入一个值为X的新节点。
——关于什么时候需要用malloc函数申请空间的思考:
当我们需要构造一个全新节点的时候,需要申请空间;但是当仅仅是使用新指针变量指向一个已经存在的节点的时候,不需要重新申请空间。因为两个指针变量指向了同一个结点,无需开辟新的空间。

void Insert(int X,int i,List PtrL)
{//创建一个新节点List new = malloc(sizeof(struct LNode));new->data = X;//代码的健壮性if(i == 1)//特殊位置:表头{new->Next = PtrL;//这样链表头就发生了改变,要调用new作为表头}else if(i == length(PtrL)+1)//特殊位置:表尾(也就是说直接在表尾增加一个新的节点){FindKth(length(PtrL))->next = new;new->Next = NULL;}else if(i>length(PtrL))//检查是否合法{printf("无法插入");}else//一般位置{new->Next = FindKth(i;PtrL);//原来的第i个节点将会变成第i+1个FindKth(i-1;PtrL)->Next = new;//原来的第i-1个节点就指向了new}
}

也可以改变函数的返回类型,返回插入完成的链表头,这样就可以方便进行赋值操作PtrL = Insert(int X,int i,List PtrL);注意如果链表头变成了新创建的指针new,那么原来的PtrL就相当于指向了链表的第二个结点。一般情况下函数返回头指针赋值给PtrL,保持PtrL作为头指针不变。

删除

删除链表中的第i个节点,就将第i-1个节点直接指向第i+1个节点,跳过第i个节点,完成连接。注意删掉的结点i是要释放空间的。

List Delete(int i,List PtrL)
{List s;//先考虑一头一尾if(i == 1)//删除的是头结点{if(PtrL != NULL)//考虑链表是否是空的{s = FindKth(i,PtrL);free(s);PtrL = PtrL->Next;}else printf("整个链表是空链表,没法再删了");}else if(i = length(PtrL)){s = FindKth(i,PtrL);free(s);FindKth(i-1,PtrL)->Next = NULL;}else if(i<=0 || i>length(PtrL))//检查合法性{printf("请输入合法的位置!");}else//一般情况{s = FindKth(i,PtrL);free(s);FindKth(i-1,PtrL)->Next = FindKth(i+1,PtrL); }return Ptrl;
}

3.广义表和多重链表

广义表

在这里插入图片描述
将二元多项式整理成一元多项式,使用链表。
数据部分:系数(一元多项式)、指数次方;link部分指向下一个节点。
也就是说,在关于x的一元多项式里面嵌套了关于y的一元多项式。原来线性表的系数部分是常量,只不过现在变成了有关y的一元多项式。
在这里插入图片描述

广义表就属于多重链表

在这里插入图片描述
多重链表中的节点可能属于多个链,也就是说它里面会有多个指针域,分别指向不同链中的下个节点。
eg.矩阵
在这里插入图片描述
稀疏矩阵就是0项非常多,使用数组就会造成大量的空间储存的是0,空间浪费严重。
在这里插入图片描述

十字链表来实现稀疏矩阵

data部分:行坐标i、列坐标j、元素的值A(i,j);
指针域LInk部分:行指针Right、列指针Down,是指向同一行中下一个节点和同一列中下一个节点的指针。
也就是说每个节点都需要与他最近的列和行的元素连接起来。每个节点同时属于他所在的行和他所在列。
在这里插入图片描述

  • 这里有两种类型的节点。
    一种是Term类型代表矩阵中的非零项,data表示的是行、列、数值,它具有两个指针(行、列),同一行同一列都设计成循环链表。
    另一种是Head节点,不同的Head作为了行链表的头结点、列链表的头结点。
    在这里插入图片描述
  • 左上角的Term节点比较特殊,他是整个矩阵的入口,他的行值、列值、数值4,5,7,表示这个矩阵有4行5列,非零项个数有7个。他也具有两个指针,通过这两个指针就可以找到所有列的头结点和所有行的头结点。他就是整个矩阵的说明信息。
#include <stdio.h>
#include <stdlib.h>// 定义稀疏矩阵的节点结构体
typedef struct Node {int row, col, value;struct Node* right;struct Node* down;
} Node;// 创建新节点的函数
Node* createNode(int row, int col, int value) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->row = row;newNode->col = col;newNode->value = value;newNode->right = NULL;newNode->down = NULL;return newNode;
}// 定义稀疏矩阵结构体
typedef struct SparseMatrix {int rows, cols;Node* head; // 头指针
} SparseMatrix;// 创建稀疏矩阵的函数
SparseMatrix createSparseMatrix(int m, int n) {SparseMatrix matrix;matrix.rows = m;matrix.cols = n;// 创建头指针节点,表示头结点matrix.head = createNode(-1, -1, 0);matrix.head->right = matrix.head; // 将右指针和下指针指向自身,构成一个环形链表matrix.head->down = matrix.head;return matrix;
}// 向稀疏矩阵插入元素的函数
void insert(SparseMatrix* matrix, int row, int col, int value) {Node* newNode = createNode(row, col, value);Node* currentRow = matrix->head;while (currentRow->down != matrix->head && currentRow->down->row < row) {currentRow = currentRow->down;}Node* currentColumn = currentRow;while (currentColumn->right != currentRow && currentColumn->right->col < col) {currentColumn = currentColumn->right;}newNode->right = currentColumn->right;currentColumn->right = newNode;currentColumn = matrix->head;while (currentColumn->right != matrix->head && currentColumn->right->col < col) {currentColumn = currentColumn->right;}newNode->down = currentColumn->right;currentColumn->right = newNode;
}int main() {SparseMatrix matrix = createSparseMatrix(3, 3); // 创建一个3x3的稀疏矩阵insert(&matrix, 0, 2, 5); // 向矩阵中插入元素insert(&matrix, 1, 1, 3);insert(&matrix, 2, 0, 4);return 0;
}

在这里插入图片描述

在调用指针之前一定要保证指针的内容是存在的而不是NULL
while(p && p->data != e)//当p存在并且...
{
}

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

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

相关文章

MySQL、Oracle查看字节和字符长度个数的函数

目录 0. 总结1. MySQL1.1. 造数据1.2. 查看字符/字节个数 2. Oracle2.1. 造数据2.2. 查看字符/字节个数 0. 总结 databasecharacterbyteMySQLchar_length()length()Oraclelength()lengthB() 1. MySQL 1.1. 造数据 drop table if exists demo; create table demo (id …

手机一键换ip地址,解锁网络自由

在数字化时代&#xff0c;手机已经成为我们生活中不可或缺的一部分。随着移动互联网的快速发展&#xff0c;手机用户对于网络安全和隐私保护的需求也日益增强。其中&#xff0c;IP地址作为手机在网络中的标识&#xff0c;扮演着重要的角色。有时&#xff0c;出于隐私保护或网络…

WebSocket用户验证

在WebSocket中&#xff0c;如何携带用户的验证信息 一、在OnMessage中进行验证 客户端在连接到服务器后&#xff0c;客户端通过发送消息&#xff0c;服务器端在OnMessage方法中&#xff0c;进行信息验证&#xff0c;这种方式需要将用户身份验证及接收用户消息进行混合处理&am…

Python人工智能:推动气象科学研究与技术进步的新动力

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

Oracle 数据库中的全文搜索

Oracle 数据库中的全文搜索 0. 引言1. 整体流程2. 创建索引2-1. 创建一个简单的表2-2. 创建文本索引2-3. 查看创建的基础表 3. 运行查询3-1. 运行文本查询3-2. CONTAINS 运算符3-3. 混合查询3-4. OR 查询3-5. 通配符3-6. 短语搜索3-7. 模糊搜索&#xff08;Fuzzy searches&…

2021-08-06

yarn的简介&#xff1a; Yarn是facebook发布的一款取代npm的包管理工具。 yarn的特点&#xff1a; 速度超快。 Yarn 缓存了每个下载过的包&#xff0c;所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率&#xff0c;因此安装速度更快。超级安全。 在执行代码…

Redis性能瓶颈与安全隐患排查验证纪实

在写《Redis怎样保证数据安全&#xff1f;》这篇文章&#xff0c;我是有对redis设置密码需要哪些步骤&#xff0c;设置密码的性能损耗有验证的。这就涉及到要对redis的配置做修改。 开始时我是打算采用直接使用redis配置文件的方式。所以我从redis官网下载了一个默认的配置文件…

ROS 2边学边练(9)-- 用launch命令管理启动项

概念 我们在前面的ROS 2体验过程中&#xff0c;一直拿小海龟这个例子来练手&#xff0c;过程比较轻松&#xff0c;因为只有两个节点&#xff08;/turtlesim和/teleop_turtle&#xff09;&#xff0c;只需打开两个终端&#xff0c;ros2 run 节点就ok&#xff0c;但&#xff0c;现…

Datacom HCIP笔记-ISIS协议

IS中间系统&#xff08;路由器/运行了ISIS协议的设备&#xff09; ES终端系统(PC,PAD,print) 网络功能模型 ISO定义 事实标准 OSI TCP/IP 网络层(CLNP) (IS-IS) 网络…

EfficientVMamba实战:使用EfficientVMamba实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构编译安装Vim环境环境安装过程安装库文件 计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2401.09417v1.pdf 作者研究了轻量级模型设计的新方法&#xff0c;通过引入视觉状态空间模型&…

Git、TortoiseGit、SVN、TortoiseSVN 的关系和区别

Git、TortoiseGit、SVN、TortoiseSVN 的关系和区别 &#xff08;二&#xff09;Git&#xff08;分布式版本控制系统&#xff09;:&#xff08;二&#xff09;SVN&#xff08;集中式版本控制系统&#xff09;&#xff08;三&#xff09;TortoiseGit一、下载安装 git二、安装过程…

Tomcat调优总结

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置。首先是对这几个参数的含义要有深刻而清楚的理解。以tomcat8.5为例&#xff0c;讲解参数。 同时也得认识到一点&#xff0c;tomcat调优也受制于linux内核。linux内核对tcp连接也有几个参数可以调优。 因此可以将…

scala实现通过Spark统计人均登录次数最终写入MySQL

谨以此博客作为记录 小编这里用的版本是&#xff1a; <hadoop.version>2.7.7</hadoop.version> <spark.version>2.4.5</spark.version> <scala.version>2.12.10</scala.version> 如果没用到Hadoop可以忽略 步骤 准备数据&#xff0c;知道…

C++面向对象程序设计 - 访问对象中成员的3种方法

在C程序中访问对象的成员变量和成员函数&#xff0c;有三种方法&#xff1a; 通过对象名和成员运算符访问对象中的成员&#xff1b;通过指向对象的指针访问对象中的成员&#xff1b;通过对象的引用变量访问对象中的成员 在了解访问对象中成员的3种方法前&#xff0c;先了解下C…

网络安全之IP地址证书的重要性

在数字化时代&#xff0c;网络空间已成为各类活动的重要载体&#xff0c;无论是商业交易、信息交流还是远程办公&#xff0c;都离不开互联网的支撑。然而&#xff0c;网络环境的开放性与匿名性也带来了安全风险&#xff0c;如何确保网络交互中的身份真实可信&#xff0c;成为了…

【御控物联】JSON结构数据转换在物联业务中应用(场景案例二)

文章目录 一、物联网业务场景现状二、物联网业务场景数据交互格式三、JSON格式数据转换案例四、JSON数据格式转换DEMO五、在线转换工具六、技术资料 一、物联网业务场景现状 目前&#xff0c;市场上多数物联网关与物联平台捆绑售卖&#xff0c;网关采集到设备数据只能按照指定…

Excel·VBA二维数组组合函数之穷举推理题

看到一个帖子《CSDN-求助一道推理题》&#xff0c;与之前《python穷举暴力破解《2018年刑侦推理题》用python穷举的推理题很类似 那么是否可以使用《ExcelVBA二维数组组合函数、组合求和》combin_arr2d函数&#xff0c;生成结果进行穷举呢&#xff1f; Sub 穷举推理题()Dim …

修改Gradio界面中按钮Submit、Clear,Flag为中文,修改additional_inputs标签。

展示如图 Submit、Clear、additional_inputs标签 Submit、Clear修改 修改gradio库中interface.py additional_inputs标签 同一文件下 flag修改 flag展示

壁纸小程序Vue3(自定义头部组件)

1.自定义头部 coustom-nav <view class"layout"><view class"navbar"><view class"statusBar"></view><view class"titleBar"><view class"title">标题</view><view class&qu…

卷积神经网络(CNN)的数学原理解析

文章目录 前言 1、介绍 2、数字图像的数据结构 3、卷积 4、Valid 和 Same 卷积 5、步幅卷积 6、过渡到三维 7、卷积层 8、连接剪枝和参数共享 9、卷积反向传播 10、池化层 11、池化层反向传播 前言 本篇主要分享卷积神经网络&#xff08;CNN&#xff09;的数学原理解析&#xf…