《数据结构与算法设计》实验报告书之字符串和数组的基本操作

《数据结构与算法设计》实验报告书之字符串和数组的基本操作

实验项目
       字符串和数组的基本操作

实验目的
       1.掌握数组的定义
       2.理解求稀疏矩阵的转置矩阵算法在三元组表示上的实现。

实验内容
       1.利用C语言实现数组的定义。
       2.实现稀疏矩阵的三元组表示以及转置算法。

算法设计分析

(一)数据结构的定义
       有时候我们的矩阵中只有零星的一些非零元素,其余的都是零元素,那么我们称之为稀疏矩阵,当然没有绝对的说有多少个零元素才算稀疏。简单说,稀疏矩阵就是非零元素个数远远小于元素个数的矩阵。相对于稀疏矩阵来说,一个不稀疏的矩阵也称作稠密矩阵。针对上面的这个无规律的存放非零元素,三元组提出了一种方法,就是仅仅记录矩阵中的非零元素以及它的行,列以及值N(x,y,v)构成的一个三元组,标识一个稀疏矩阵的话,还要记录该矩阵的阶数,这样我们就将一个二维的变成了一个一维,极大的压缩的存储空间。 这里要注意的就是,三元组的构建采用“行”是从上到下,“列”也是从左到右的方式构建的顺序表。
顺序表存储结构定义为:

/*定义稀疏矩阵三元组*/
#define MAXSIZE 12500
typedef  struct {
	int  i, j;    //该非零元的行列下标
	int e;
}Triple;
typedef  struct {
	Triple  data[MAXSIZE];
	int mu, nu, tu;
	//矩阵的行、列数和非零元个数
}TSMatrix;

(二)总体设计
       实验总共包括五个函数:主函数,初始化稀疏矩阵三元组函数,打印稀疏矩阵三元组函数,转置稀疏矩阵三元组函数,快速转置稀疏矩阵三元组函数。

主函数:统筹调用各个函数以实现相应功能
Int main()
Void opration()

初始化稀疏矩阵三元组函数:建立初始化稀疏矩阵三元组
Void init ()

打印稀疏矩阵三元组函数:打印稀疏矩阵三元组构成的稀疏矩阵
Int Print()

转置稀疏矩阵三元组函数:利用普通方法遍历转置稀疏矩阵
Void exchange()

快速转置稀疏矩阵三元组函数:利用快速方法直接转置稀疏矩阵
Void quickly ()

(三)各函数的详细设计:
主函数main()
主要就是进行功能的实现。

初始化稀疏矩阵三元组函数init():
建立初始化稀疏矩阵三元组,初始行,列,值的个数,再一一存入数据。

打印稀疏矩阵三元组函数Print()
将稀疏矩阵三元组构成的稀疏矩阵以数组的方式打印出来。

转置稀疏矩阵三元组函数exchange()
利用普通方法遍历转置稀疏矩阵,两层循环直接嵌套遍历整个二维数组,复杂度较高,效率不大。

快速转置稀疏矩阵三元组函数quickly()
利用快速方法遍历转置稀疏矩阵,直接使用一层循环,再遍历数据的同时把位置记下来,在其中找的时候直接把值放在了指定的位置,比起普通的方法快了很多。

实验测试结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验总结:(100字到200字)

(1)调试过程中主要遇到哪些问题?是如何解决的?
答:稀疏矩阵三元组的难度有点大,遇见的问题有一些。
1.在一开始打印时遇见数据打印不出来的问题,结果发现是由于初始化函数传值时没有使用&符号,导致三元组的数没有传入。
2.在进行普通转置函数的时候,没有想到需要用两个三元组来存放数据,导致走了很多的歪路,后来发现,有另一个三元组来存放数据比较方便快捷。
3.在快速转置的函数中,有些地方的逻辑还是不怎么清楚,需要加深理解,尤其是找位置的数组是如何来的。

(2)经验和体会
答:还是那句老话,多敲代码自己练习,有时间把多复习多看看书,增加自己对快速转置的理解能力。

附录 实验程序代码(该部分请加注释)

/SeqList.h函数代码/


//#ifndef SEQLIST_H_INCLUDED
//#define SEQLIST_H_INCLUDED

#define MAXSIZE 12500
typedef  struct {
	int  i, j;    //该非零元的行列下标
	int e;      //该元素的值
}Triple;
typedef  struct {
	Triple  data[MAXSIZE];
	int mu, nu, tu;
	//矩阵的行、列数和非零元个数
}TSMatrix;

void init(TSMatrix &s)
{
	int i;
	std::cout<<"请输入需要打的行,列,值!!"<<std::endl;
	std::cin>>s.mu>>s.nu>>s.tu; //输入每个值得位置以及值
	for(i=0;i<s.tu;i++){//循环输入
		std::cout<<"请输入第"<<i+1<<"的行号,列号,值:"<<std::endl;
		std::cin>>s.data[i].i>>s.data[i].j>>s.data[i].e;
	}
}

void Print(TSMatrix t)//打印函数
{
	int time=0,i,j;
	for(i=0;i<t.mu;i++)
		for(j=0;j<t.nu;j++)
		{
			if(t.data[time].i==i&&t.data[time].j==j)//压缩矩阵不断输出
			{
				std::cout<<t.data[time].e;
				time++;
			}
			else
				std::cout<<"0";
			if(j!=t.nu-1)//格式控制
				std::cout<<" ";
			else
				std::cout<<std::endl;
		}
}
void exchange(TSMatrix s,TSMatrix &t){//普通转置函数
	t.mu=s.nu; t.nu=s.mu; t.tu=s.tu;//直接交换两个三元组得行数和列数
	if (t.tu)//如果值的个数不为零就进入程序
	{
		int q = 0;//第二个三元组的下标
		for (int col = 0;  col < s.nu;  col++){//按照顺序来循环找值
			for (int p = 0; p < s.tu;   p++){//遍历每个数据
				if ( s.data[p].j == col )//如果对应的位置有值,则进入下面语句
				{
					t.data[q].i = s.data[p].j ;//交换行和列
					t.data[q].j = s.data[p].i ;
					t.data[q].e = s.data[p].e;//赋值
					++ q;//下标加加
				}
			}
		}
	}
}

void quickly(TSMatrix M,TSMatrix &T)//快速转置函数
{
	int num[200],cpot[200],q,col,t,p;//定义两个数组,第一个用来统计相同列的个数,另一个用来求位置。
	T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;//交换
	if (T.tu) {
		for ( col=0; col<M.nu; ++col)
			num[col] = 0;//初始化
		for ( t=0; t<M.tu; ++t)
			num[M.data[t].j]++;//统计相同列的个数
		// 求 M 中各列非零元的个数
		cpot[0] = 0;
		for ( col=1;col<M.nu;col++)
		  cpot[col] = cpot[col -1] + num[col -1];//求位置
		for ( p=0; p<M.tu; ++p) {  // 转置矩阵元素
		  col = M.data[p].j;
		  q = cpot[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;
		  ++ cpot[col];//进行完之后加1,表示往后移动一位
		}
	}
}
//#endif // SEQLIST_H_INCLUDED

/menu.h菜单函数代码/

#ifndef MENU_H_INCLUDED
#define MENU_H_INCLUDED

void menu(){
    std::cout<<"\n";
    std::cout<<" ************************矩阵转置************************\n";
    std::cout<<" *                                                      *\n";
    std::cout<<" *     a:创建矩阵            b:转置矩阵                 *\n";
    std::cout<<" *     c:打印矩阵            d:快速转置矩阵             *\n";
    std::cout<<" *     e:退出                                           *\n";
    std::cout<<" *                                                      *\n";
    std::cout<<" ********************************************************\n";
}

#endif // MENU_H_INCLUDED

/主函数代码/

#include <iostream>
#include "menu.h"
#include "Array.h"
using namespace std;
int main()
{
	void opration();
	opration();
	return 0;
}
void opration(){
	for(;;){
		TSMatrix s,t,r;
		menu();
		char a;
		cin>>a;
		switch(a){
		case 'a':
			init(s);
			Print(s);
			break;
		case 'b':
			exchange(s,t);
			cout<<"转置之前的矩阵为:"<<endl;
			Print(s);
			cout<<"转置之后的矩阵为:"<<endl;
			Print(t);
			break;
		case 'c':
			cout<<"打印的矩阵为:"<<endl;
			Print(s);
			break;
		case 'd':
			quickly(s,r);
			cout<<"快速转置之前的矩阵为:"<<endl;
			Print(s);
			cout<<"快速转置之后的矩阵为:"<<endl;
			Print(r);
			break;
		case 'e':
			cout<<"拜拜!!"<<endl;
			return ;
			break;
		default:
			cout<<"你输入的序号不正确!!"<<endl;
			break;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42967398/article/details/84941619
今日推荐