稀疏矩阵的三元组行逻辑链接的顺序表存储表示和实现(第五章 P101 算法5.3)

稀疏矩阵的三元组行逻辑链接的顺序表存储

 

三元组行逻辑链接顺序表存储结构:                                         采用三元组行逻辑链接存储稀疏矩阵的实例:

 

三元组行逻辑链接的顺序表存储表示 比三元组顺序表存储表示 增加 了 rpos 数组,用以存放各行的第一个非零元素在 data 数组中的位置。这样,就可以迅速地 找到某一行的元素。(创建稀疏矩阵输入非零元时,也要按行、列的顺序由小到大输入。)
 
 
 
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

#include<stdarg.h> /* 标准头文件,提供宏va_start,va_arg和va_end, */
/* 用于存取变长参数表 */

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 



/* ---------------------------  稀疏矩阵的三元组行逻辑链接的顺序表存储表示  ------------------------------*/

#define MAXSIZE 100 /* 非零元个数的最大值 */
#define MAXRC 20 /* 最大行列数 */
typedef struct
{
	int i, j; /* 行下标,列下标 */
	ElemType e; /* 非零元素值 */
}Triple; /* 同c5-2.h */
typedef struct
{
	Triple data[MAXSIZE + 1]; /* 非零元三元组表,data[0]未用 */
	int rpos[MAXRC + 1]; /* 各行第一个非零元素的位置表,比c5-2.h增加的项 */
	int mu, nu, tu; /* 矩阵的行数、列数和非零元个数 */
}RLSMatrix;

/* ------------------------------------------------------------------------------------------*/



/* ---------------------------  行逻辑链接稀疏矩阵的基本操作(8个)  --------------------------*/

Status CreateSMatrix(RLSMatrix *M)
{ /* 创建稀疏矩阵M */
	int i;
	Triple T;
	Status k;
	printf("请输入矩阵的行数,列数,非零元素数:");
	scanf_s("%d,%d,%d", &(*M).mu, &(*M).nu, &(*M).tu);
	(*M).data[0].i = 0; /* 为以下比较做准备 */
	for (i = 1; i <= (*M).tu; i++)
	{
		do
		{
			printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:", i, (*M).mu, (*M).nu);
			scanf_s("%d,%d,%d", &T.i, &T.j, &T.e);
			k = 0;
			if (T.i<1 || T.i>(*M).mu || T.j<1 || T.j>(*M).nu) /* 行、列超出范围 */
				k = 1;
			if (T.i < (*M).data[i - 1].i || T.i == (*M).data[i - 1].i&&T.j <= (*M).data[i - 1].j) /* 没有按顺序输入非零元素 */
				k = 1;
		} while (k); /* 当输入有误,重新输入 */
		(*M).data[i] = T;
	}
	for (i = 1; i <= (*M).tu; i++) /* 计算rpos[] */
		if ((*M).data[i].i > (*M).data[i - 1].i)
			for (T.i = 0; T.i < (*M).data[i].i - (*M).data[i - 1].i; T.i++)
				(*M).rpos[(*M).data[i].i - T.i] = i;
	for (i = (*M).data[(*M).tu].i + 1; i <= (*M).mu; i++) /* 给最后没有非零元素的几行赋值 */
		(*M).rpos[i] = (*M).tu + 1;
	return OK;
}

void DestroySMatrix(RLSMatrix *M)
{ /* 销毁稀疏矩阵M(使M为0行0列0个非零元素的矩阵) */
	(*M).mu = 0;
	(*M).nu = 0;
	(*M).tu = 0;
}

void PrintSMatrix(RLSMatrix M)
{ /* 输出稀疏矩阵M */
	int i;
	printf("%d行%d列%d个非零元素。\n", M.mu, M.nu, M.tu);
	printf("行  列  元素值\n");
	for (i = 1; i <= M.tu; i++)
		printf("%2d%4d%8d\n", M.data[i].i, M.data[i].j, M.data[i].e);
	for (i = 1; i <= M.mu; i++)
		printf("第%d行的第一个非零元素是本矩阵第%d个元素\n", i, M.rpos[i]);
}

void PrintSMatrix1(RLSMatrix M)
{ // 按矩阵形式输出M
	int i, j, k = 1;
	Triple *p = M.data;
	p++; // p指向第1个非零元素
	for (i = 1; i <= M.mu; i++)
	{
		for (j = 1; j <= M.nu; j++)
			if (k <= M.tu&&p->i == i && p->j == j) // p指向非零元,且p所指元素为当前处理元素
			{
				printf("%3d", p->e); // 输出p所指元素的值
				p++; // p指向下一个元素
				k++; // 计数器+1
			}
			else // p所指元素不是当前处理元素
				printf("%3d", 0); // 输出0
			printf("\n");
	}
}

Status CopySMatrix(RLSMatrix M, RLSMatrix *T)
{ /* 由稀疏矩阵M复制得到T */
	*T = M;
	return OK;
}

Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵的和Q=M+N */
	int k, p, q;
	if (M.mu != N.mu || M.nu != N.nu)
		return ERROR;
	(*Q).mu = M.mu;
	(*Q).nu = M.nu;
	(*Q).tu = 0;
	M.rpos[M.mu + 1] = M.tu + 1; /* 为方便后面的while循环临时设置 */
	N.rpos[N.mu + 1] = N.tu + 1;
	for (k = 1; k <= M.mu; ++k) /* 对于每一行,k指示行号 */
	{
		(*Q).rpos[k] = (*Q).tu + 1;
		p = M.rpos[k]; /* p指示M矩阵第k行当前元素的序号 */
		q = N.rpos[k]; /* q指示N矩阵第k行当前元素的序号 */
		while (p < M.rpos[k + 1] && q < N.rpos[k + 1])
		{ /* M,N矩阵均有第k行元素未处理 */
			if (M.data[p].j == N.data[q].j) /* M矩阵当前元素和N矩阵当前元素的列相同 */
			{
				(*Q).data[(*Q).tu + 1].e = M.data[p].e + N.data[q].e;
				if ((*Q).data[(*Q).tu + 1].e != 0)
				{
					++(*Q).tu;
					(*Q).data[(*Q).tu].i = k;
					(*Q).data[(*Q).tu].j = M.data[p].j;
				}
				++p;
				++q;
			}
			else if (M.data[p].j < N.data[q].j)
			{ /* M矩阵当前元素的列<N矩阵当前元素的列 */
				++(*Q).tu;
				(*Q).data[(*Q).tu].e = M.data[p].e;
				(*Q).data[(*Q).tu].i = k;
				(*Q).data[(*Q).tu].j = M.data[p].j;
				++p;
			}
			else /* M矩阵当前元素的列>N矩阵当前元素的列 */
			{
				++(*Q).tu;
				(*Q).data[(*Q).tu].e = N.data[q].e;
				(*Q).data[(*Q).tu].i = k;
				(*Q).data[(*Q).tu].j = N.data[q].j;
				++q;
			}
		}
		while (p < M.rpos[k + 1]) /* M矩阵还有k行的元素未处理 */
		{
			++(*Q).tu;
			(*Q).data[(*Q).tu].e = M.data[p].e;
			(*Q).data[(*Q).tu].i = k;
			(*Q).data[(*Q).tu].j = M.data[p].j;
			++p;
		}
		while (q < N.rpos[k + 1]) /* N矩阵还有k行的元素未处理 */
		{
			++(*Q).tu;
			(*Q).data[(*Q).tu].e = N.data[q].e;
			(*Q).data[(*Q).tu].i = k;
			(*Q).data[(*Q).tu].j = N.data[q].j;
			++q;
		}
	}
	return OK;
}

Status SubtSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵的差Q=M-N */
	int i;
	if (M.mu != N.mu || M.nu != N.nu)
		return ERROR;
	for (i = 1; i <= N.tu; ++i) /* 对于N的每一元素,其值乘以-1 */
		N.data[i].e *= -1;
	AddSMatrix(M, N, Q); /* Q=M+(-N) */
	return OK;
}

Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{ /* 求稀疏矩阵乘积Q=M*N。算法5.3 */
	int arow, brow, p, q, ccol, ctemp[MAXRC + 1];
	if (M.nu != N.mu) /* 矩阵M的列数应和矩阵N的行数相等 */
		return ERROR;
	(*Q).mu = M.mu; /* Q初始化 */
	(*Q).nu = N.nu;
	(*Q).tu = 0;
	M.rpos[M.mu + 1] = M.tu + 1; /* 为方便后面的while循环临时设置 */
	N.rpos[N.mu + 1] = N.tu + 1;
	if (M.tu*N.tu != 0) /* M和N都是非零矩阵 */
	{
		for (arow = 1; arow <= M.mu; ++arow)
		{ /* 从M的第一行开始,到最后一行,arow是M的当前行 */
			for (ccol = 1; ccol <= (*Q).nu; ++ccol)
				ctemp[ccol] = 0; /* Q的当前行的各列元素累加器清零 */
			(*Q).rpos[arow] = (*Q).tu + 1; /* Q当前行的第1个元素位于上1行最后1个元素之后 */
			for (p = M.rpos[arow]; p < M.rpos[arow + 1]; ++p)
			{ /* 对M当前行中每一个非零元 */
				brow = M.data[p].j; /* 找到对应元在N中的行号(M当前元的列号) */
				for (q = N.rpos[brow]; q < N.rpos[brow + 1]; ++q)
				{
					ccol = N.data[q].j; /* 乘积元素在Q中列号 */
					ctemp[ccol] += M.data[p].e*N.data[q].e;
				}
			} /* 求得Q中第arow行的非零元 */
			for (ccol = 1; ccol <= (*Q).nu; ++ccol) /* 压缩存储该行非零元 */
				if (ctemp[ccol])
				{
					if (++(*Q).tu > MAXSIZE)
						return ERROR;
					(*Q).data[(*Q).tu].i = arow;
					(*Q).data[(*Q).tu].j = ccol;
					(*Q).data[(*Q).tu].e = ctemp[ccol];
				}
		}
	}
	return OK;
}

Status TransposeSMatrix(RLSMatrix M, RLSMatrix *T)
{ /* 求稀疏矩阵M的转置矩阵T */
	int p, q, t, col, *num;
	num = (int *)malloc((M.nu + 1) * sizeof(int));
	(*T).mu = M.nu;
	(*T).nu = M.mu;
	(*T).tu = M.tu;
	if ((*T).tu)
	{
		for (col = 1; col <= M.nu; ++col)
			num[col] = 0;  /* 设初值 */
		for (t = 1; t <= M.tu; ++t) /* 求M中每一列非零元个数 */
			++num[M.data[t].j];
		(*T).rpos[1] = 1;
		for (col = 2; col <= M.nu; ++col) /* 求M中第col中第一个非零元在(*T).data中的序号 */
			(*T).rpos[col] = (*T).rpos[col - 1] + num[col - 1];
		for (col = 1; col <= M.nu; ++col)
			num[col] = (*T).rpos[col];
		for (p = 1; p <= M.tu; ++p)
		{
			col = M.data[p].j;
			q = num[col];
			(*T).data[q].i = M.data[p].j;
			(*T).data[q].j = M.data[p].i;
			(*T).data[q].e = M.data[p].e;
			++num[col];
		}
	}
	free(num);
	return OK;
}

/* ------------------------------------------------------------------------------------------*/


/*  检验以上操作的主程序 */

void main()
{
	RLSMatrix A, B, C; 
	printf("创建矩阵A: ");
	CreateSMatrix(&A);
	PrintSMatrix1(A);
	printf("由矩阵A复制矩阵B: ");
	CopySMatrix(A, &B);
	PrintSMatrix1(B);
	DestroySMatrix(&B);
	printf("销毁矩阵B后:\n");
	PrintSMatrix1(B);
	printf("创建矩阵B2:(与矩阵A的行、列数相同,行、列分别为%d,%d)\n", A.mu, A.nu);
	CreateSMatrix(&B);
	PrintSMatrix1(B);
	printf("矩阵C1(A+B): ");
	AddSMatrix(A, B, &C);
	PrintSMatrix1(C);
	DestroySMatrix(&C);
	printf("矩阵C2(A-B): ");
	SubtSMatrix(A, B, &C);
	PrintSMatrix1(C);
	DestroySMatrix(&C);
	printf("矩阵C3(A的转置): ");
	TransposeSMatrix(A, &C);
	PrintSMatrix1(C);
	DestroySMatrix(&A);
	DestroySMatrix(&B);
	DestroySMatrix(&C);
	printf("创建矩阵A2: ");
	CreateSMatrix(&A);
	PrintSMatrix1(A);
	printf("创建矩阵B3:(行数应与矩阵A2的列数相同=%d)\n", A.nu);
	CreateSMatrix(&B);
	PrintSMatrix1(B);
	printf("矩阵C5(A*B): ");
	MultSMatrix(A, B, &C);
	PrintSMatrix1(C);
	DestroySMatrix(&A);
	DestroySMatrix(&B);
	DestroySMatrix(&C);
}

运行结果:

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资源简介】 基于蚁群算法实现寻找最优路径matlab源码+项目说明+超详细注释.zip 与Dijkstra算法使用相同的地图。 每只蚂蚁都从起点出发,直到抵达终点。这与Example5_1.m 中解决旅商问题不一样,旅商问题中每一代的蚂蚁都是随机从一个节点出发。 文件说明 Example5_1.m 简单对参考资料2中的代码进重现; ACA.m 对参考资料1中的代码进重现,并适当优化代码且修改错误,错误如下: ![错误1](./imgs/1.jpg) 计算P(2,k)有问题,neighbor已经删除了不可访问节点,所以neighbor中节点的索引和nodes_data{node_step, 4}索引不是一一对应关系,应该先找到对应的索引。 修正: ![修正1](./imgs/2.jpg) 实验 **信息素启发式因子α** 代表信息量对是否选择当前路径的影响程度, 即反映蚂蚁在运动过程中所积累的信息量在指导蚁群搜索中的相对重要程度。 α 的大小反映了蚁群在路径搜索中随机性因素作用的强度, 其越大, 蚂蚁在选择以前走过的路径的可能性就越大, 搜索的随机性就会减弱; 而当启发式因子α的过小, 则易使蚁群的搜索过早陷于局部最优。 根据经验, 信息素启发式因子α取范围一般为[l, 4], 蚁群算法的综合求解性能较好。 **期望启发因子β** 表示在搜索路径上的信息素在指导蚂蚁选择路径的向导性, 它的大小反映了蚁群在搜索最优路径的过程中的先验性和确定性因素的作用强度。 期望启发因子β的越大, 蚂蚁在某个局部点上选择局部最短路径的可能性就越大, 虽然这个算法的收敛速度得以加快, 但蚁群搜索最优路径的随机性减弱, 而此搜索易于陷入局部最优解。 根据经验, 期望启发因子β取范围一般为[3, 5], 此蚁群算法的综合求解性能较好。 参考:《智能优化算法及其MATLAB实例(第2版)》by包子阳 P101 例5.1 对结果的显示进一定修改,以查看每一次迭代的最佳结果: ![代码修改](./imgs/0.jpg) ![地图](./imgs/6.jpg) Dijkstra算法示例中求出的最优路径为:4-5-6-1 修改$\beta$重复四次实验 1. $\beta=0$ 实践中$\beta$不应等于0,但为了说明距离这样的先验信息起的作用,取$\beta=0$,实验结果: ![实验](./imgs/3.jpg) 2. $\beta=3$ ![实验](./imgs/4.jpg) 3. $\beta=5$ ![实验](./imgs/5.jpg) 对比三个实验中纵坐标最小可以看出,$\beta$越大,算法越易陷入局部最优。 1. 实验一最优全为22,是全局最优,最优路径 4-5-6-1。 2. 实验二2个22,2个25; 3. 实验三全为25,均为局部最优,局部最优路径 4-5-6-2-1。 讨论: - 位于节点6,接下来应该选择节点1还是节点2受到信息素和启发因子的影响,当$\beta$较大,更看重启发信息,即更加偏向与选择距离短的节点(节点6->节点1距离为16,节点6->节点2距离为7),因此才会出现实验三的结果。当$\beta=0$,启发信息不起作用,选择全取决于信息素,这种情况更贴近自然中的蚁群寻路。 - 群智能算法都有陷入局部最优的问题 【说明】 1、项目源码在上传前,都经过本地成功运,功能测试无误。请放心下载使用!有问题请及沟通交流。 2、适用人群:计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、机械电子信息等相关专业背景的在校大学生、专业老师 业从业人员等下载使用。 3、用途:项目代表性强,具有创新性和启发性,故具有挺高的学习借鉴价。不仅适合小白入门进阶,还可作为毕设项目、课程设计、大作业、比赛初期项目立项演示等。 4、如果基础还不错,又热爱学习钻研,也可基于此项目基础上进修改进二次开发。 本人也是技术狂热者,如果觉得此项目对您有价,欢迎下载使用! 无论您是运还是二次开发,遇到问题或困惑,欢迎私信交流学习。
本章学习目标 了解影响计算机安全的因素,学会如何保障个人计算机系统安全和基本网络安全,具备解决与应对计算机系统问题的能力。 本章要点 影响计算机安全的因素 如何保护自己的计算机系统 计算机系统出现问题后如何应对 《计算机应用技术基础》第四章全文共22页,当前为第1页。 影响计算机安全的因素 计算机病毒 木马 蠕虫 流氓软件 欺骗与陷阱 网络传播 U盘、光盘等媒介传播 《计算机应用技术基础》第四章全文共22页,当前为第2页。 计算机病毒 概念:指编制者在计算机程序中插入的破坏计算机功能或者数据,影响计算机使用并且能够自我复制的一组计算机指令或者程序代码。 特点:寄生性、传染性、潜伏性、隐蔽性、破坏性。 产生过程:程序设计 传播 潜伏 触发 运 实施攻击 《计算机应用技术基础》第四章全文共22页,当前为第3页。 木马 是一种带有恶意性质的远程控制软件。一般分为客户端和服务器端。 木马与病毒的最大区别: 木马: 主要以控制他人的计 算机为主要目的。 病毒: 会感染其他文件以破 坏为主要目的。 《计算机应用技术基础》第四章全文共22页,当前为第4页。 蠕虫 定义:是无须计算机使用者干预即可运的独立程序,通过不停地获得网络中存在漏洞的计算机上的部分或全部控制权进传播。 与病毒区别:不需人工干预、且能够自主不断地复制和传播。 工作流程:漏洞扫描— 攻击—传染---现场处理(此部 分工作包括隐藏、信息搜索) 熊猫烧香蠕虫病毒 《计算机应用技术基础》第四章全文共22页,当前为第5页。 流氓软件 这类软件虽然不会破坏系统,但会不经用户同意强侵入上网用户的电脑,强迫用户接受某些操作,或在用户不知情的情况下,强安装插件,不带卸载程序或无法彻底卸载,甚至劫持用户浏览器转到某些指定网站等。 《计算机应用技术基础》第四章全文共22页,当前为第6页。 欺骗与陷阱 利用各种诱惑使上网用户接受QQ或电子邮件传过来的软件、图片、视频等,甚至引导他人登陆事先做好的"钓鱼网站 "。这些网站传来的软件等都基本包含"木马"程序,用户很可能 在不知情的情况下将自己的账密码等信息告知他人。 《计算机应用技术基础》第四章全文共22页,当前为第7页。 网络传播 以上所说的病毒等都需传播,才能对系统进破坏。引导用户访问不明网页、下载安装不明程序、伪装发出电子邮件、QQ传播等。用户要以"防"为主,既要从技术手段上去阻断,也包括刻要有计算机安全的思想,养成良好的使用计算机的习惯。 《计算机应用技术基础》第四章全文共22页,当前为第8页。 U盘、光盘等媒介传播 除了网络传播外,U盘光盘以及其他移动设备也是病毒、木马等危害程序传播的重要途径 《计算机应用技术基础》第四章全文共22页,当前为第9页。 保护计算机系统的基本步骤 《计算机应用技术基础》第四章全文共22页,当前为第10页。 干净的系统 选择可靠的"系统软件" 购买正版系统 正确安装操作系统 全盘、C盘格式化 给系统打"补丁" 系统中自带的、第三方 《计算机应用技术基础》第四章全文共22页,当前为第11页。 防病毒、木马软件的使用 选择合适的防病毒软件、安装后升级病毒库并全盘扫描、自动/手动查杀病毒 《计算机应用技术基础》第四章全文共22页,当前为第12页。 使用安全的第三方软件 给系统打"补丁" "电脑体验" 电脑加速 《计算机应用技术基础》第四章全文共22页,当前为第13页。 系统防火墙设置和常见系统安全设置 防火墙设置:控制面板—系统和安全—Windows防火墙 《计算机应用技术基础》第四章全文共22页,当前为第14页。 系统防火墙设置和常见系统安全设置 常见系统的安全设置 设置复杂密码 系统密码设置 关闭不常用的端口P101 宏病毒保护设置 《计算机应用技术基础》第四章全文共22页,当前为第15页。 对系统进备份及养成良好的使用习惯 对系统备份 使用传统的GHOST软件 利用"一键GHOST"软件备份 养成良好的使用习惯 养成使用计算机的良好一般习惯 及备份重要资料 提高警惕、防止网络欺诈 《计算机应用技术基础》第四章全文共22页,当前为第16页。 使用计算机的良好一般习惯 分类设置密码并使密码尽可能复杂 定期升级防毒、防木马软件 将邮件、QQ、支付宝等重要账户进安全升级绑定手机 使用网上银服务,尽量使用U-Key或U盾 《计算机应用技术基础》第四章全文共22页,当前为第17页。 密码保护 邮件账户 提示密码问题、手机绑定 QQ账 设置保密问题、手机绑定 手机令牌、密保卡 异地登陆验证 支付宝 手机宝令、支付盾、数字证书,手机绑定 网上银 U-key或U盾(最安全) 《计算机应用技术基础》第四章全文共22页,当前为第18页。 使用计算机的良好习惯 备份重要资料 硬件备份(U盘、光盘、移动硬盘)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值