西工大计算机实习报告.docx
《西工大计算机实习报告.docx》由会员分享,可在线阅读,更多相关《西工大计算机实习报告.docx(17页珍藏版)》请在冰豆网上搜索。
![西工大计算机实习报告.docx](https://file1.bdocx.com/fileroot1/2023-5/25/17f5a8d5-8261-4627-afd6-5087935fd56d/17f5a8d5-8261-4627-afd6-5087935fd56d1.gif)
西工大计算机实习报告
计算机实习报告
1、趣味题
彩色的圆环:
分析图形可知,一共有n个同心圆,外面大圆n等分,然后从每个等分点作所有同心圆的两条切线。
如果用极坐标表示,可以很容易求解切点,代码如下所示:
n=10;%同心圆数量
m=40;%等分点数
R=1;%外圆半径
s=0:
0.01*pi:
2*pi;%控制圆的光滑程度的极坐标角度
t=0:
2*pi/m:
2*pi;%等分点极坐标角度
x0=R*cos(t);y0=R*sin(t);%等分点直角坐标
color=['b','r','c','g','m','y'];%画图颜色
lc=length(color);%颜色数量长度,超出后从头开始
fori=1:
n%开始同心圆循环
r=R/n*i;%当前同心圆半径
a=acos(r/R);%切线与圆心线角度(弧度制)
x1=r*cos(t-a);y1=r*sin(t-a);%任意等分点相对当前同心圆的第一个切点
x2=r*cos(t+a);y2=r*sin(t+a);%任意等分点相对当前同心圆的第二个切点
plot(r*cos(s),r*sin(s),color(mod(i,lc)+1));holdon;%画同心圆
forj=1:
m%对每一个等分点循环plot([x0(j),x1(j)],[y0(j),y1(j)],color(mod(i,lc)+1));holdon;
%第一条切线
plot([x0(j),x2(j)],[y0(j),y2(j)],color(mod(i,lc)+1));holdon;
%第二条切线
end
end
axsiequal;%横纵坐标比例一致
实验绘图结果如下图所示:
2、算法题
求无向图的最短路径(Dijkstra算法):
实验原理分析、原理及代码如下所示(此实验代码不仅包含了实验所要求的求带权无向图最短路径,我还拓展了求有向、无向、带权有向图最短路径的内容):
#include
#include
usingnamespacestd;
#definewuqiong0
classtu
{
public:
intchazhao(int);//查找
voidzjdingdian(intx);//增加顶点
tu();
voidzengjia();//控制增加弧边和点
voidzjhubian();//增加弧边
voidbianli();//控制遍历
voidshendu(int);//深度
voidguangdu(int);//广度
voidjindui(int);//进队列
intchudui();//出对了
boolpankong();//判空
//上面所有的函数与邻接矩阵有关
voidzxgouzao();//初始化与最小路劲有关的东东
voidzxshuchu();//求S中的最小路劲
private:
intkind;//类图;
intlength;//顶点个数
int*dingdian;//顶点
int*juzhen;//矩阵
intnum;//最大顶点数目
int*visted;//访问情况
int*duilie;//模拟队列
intduichang;//队列长度
//上面所有的变量与邻接矩阵有关
int*s;//存放当前顶点
intslength;//当前顶点的长度
int*dist;//存放最小路劲
int*pre;//存放路劲;
int*final;//存放顶点
};
tu:
:
tu()//初始化图
{
cout<<"请输入图的种类1:
有向.2:
无向.3:
带权有向.4:
带权无向"<cin>>kind;
cout<<"请输入图的顶点数目"<cin>>num;
dingdian=newint[num];//为顶点分配内存保存
juzhen=newint[num*num];//产生矩阵
if(kind==1||kind==2)//为无权图初始化矩阵
{
for(inti=0;ijuzhen[i]=0;
}
else//有权图初始化矩阵
{
for(inti=0;ijuzhen[i]=wuqiong;
}
length=0;
}
//增加顶点
voidtu:
:
zjdingdian(intx)
{
if(chazhao(x)!
=-1||length==num)
cout<<"图内有此顶点或图内无空间可插入,插入失败"<else
{
dingdian[length]=x;
length++;
}
}
//增加边
voidtu:
:
zjhubian()
{
inti;//弧头
intj;//弧尾
if(kind==1||kind==2)//无权图
{
cout<<"请输入弧的头和尾"<cin>>i>>j;
if(kind==1)//有向图
{
juzhen[i*num+j]=1;
}
else//无向图,两边同时取值
{
juzhen[i*num+j]=1;
juzhen[j*num+i]=1;
}
}
else//权值,同上,将1改为K(权值)即可
{
intk;
cin>>i>>j>>k;
if(kind==3)
{
juzhen[i*num+j]=k;
}
else
{
juzhen[i*num+j]=k;
juzhen[j*num+i]=k;
}
}
}
//查找,将该数所在位置返回,若无则返回-1
inttu:
:
chazhao(intx)
{
for(inti=0;iif(x==i)
returni;
return-1;
}
//控制遍历函数
voidtu:
:
bianli()//遍历函数
{
cout<<"该图的邻接矩阵为:
";
inti;
intj;
for(i=0;i{
cout<for(j=0;jcout<}
cout<visted=newint[length];//为设置访问状态定义内存空间
cout<<"深度搜索:
";
for(i=0;ivisted[i]=0;
shendu(0);//将0作为0点运用深度访问函数
cout<cout<<"广度搜索:
";
for(i=0;ivisted[i]=0;
duilie=newint[length+1];
duilie[0]=-1;//队列初始化
duichang=0;
guangdu(0);//将0作为0点运用广度访问函数
}
//深度遍历
voidtu:
:
shendu(intx)//采用递归的手法
{
intp;
visted[x]=1;//访问后置1防止重复访问
cout<p=x*length+1;
while(p%length!
=0)
{
if(juzhen[p]!
=0&&visted[p%length]!
=1)shendu(p%length);
p++;
}
}
//广度遍历
voidtu:
:
guangdu(intx)
{
intp;
visted[x]=1;
cout<p=length*x+1;
while(p%length!
=0)//没有遍历属于根节点的后代的所有兄弟结点加入到队列中(这样可以先进先出,后来的子代加入后也是先输出父亲结点)
{
if(juzhen[p]!
=0&&visted[p%length]!
=1)
{
visted[p%length]=1;//判断是否已经加入队列或访问
jindui(p%length);
}
p++;//进行下一个判断
}
while(pankong())//加入所有的子代兄弟节点后现在出队列并且访问,访问的方式一致会访问后优先加入其子代结点然后出队列访问
{
guangdu(chudui());
}
}
//进队列,在队头插入一个函数,这个出队入队为了广度输出
voidtu:
:
jindui(intx)
{
duilie[duichang+1]=-1;
duilie[duichang]=x;
duichang++;
}
//出队列,将队列中的最后一个数返回
inttu:
:
chudui()
{
intj;
j=duilie[0];
for(inti=0;iduilie[i]=duilie[i+1];
duichang--;
returnj;
}
//判空函数,函数为空的时候返回0
booltu:
:
pankong()
{
if(duichang==0)
returnfalse;
else
returntrue;
}
//控制增加函数
voidtu:
:
zengjia()
{
intj;
for(inti=0;izjdingdian(i);
cout<<"请输入需要增加的弧数(最少"<cin>>j;
cout<<"请输入弧的头和尾和权值"<for(i=0;i{
//cout<<"插入第"<
zjhubian();
}
}
/*
**算法思想:
依次递增序列求出最小路劲,首先将顶点加入到S当中(本程序默认为0号顶点),然后用dist数组保存到每一个顶点的最小路径长度
**dist起始为顶点到其他顶点的权值(到自身为0,到无弧顶点为无穷大)
**1:
然后每次取v0-vk(k属于V-S)最小的路劲长度,取完之后将Vk加入S当中。
**2:
重新对所有的dist[i(属于v-s的i)]赋值,如果新加入的那个点到i的权值小于原来的权值则dist[i]=dist[k]+wki;
**重复1,2知道S=V;退出程序
*/
voidtu:
:
zxgouzao()//最短路径求解
{
intn,i;//n为顶点
n=0;
final=newint[length];//访问状态
s=newint[length];//所求的顶点集合
dist=newint[length];//所有的最短路径
pre=newint[length];//每一个最短路径的前驱结点(利用这个将最短路径求出)
for(i=0;i{
pre[i]=n;//起初全部将前驱赋为源点
final[i]=0;//访问状态为0(即没有加入S当中)
if(i==n)//源点自身的dist为0
dist[i]=0;
else
dist[i]=juzhen[n*length+i];//源点到目标顶点的dist初始化为权值
}
pre[n]=-1;//源点前驱设为-1
s[0]=dingdian[0];//加入源点(本程序默认源点为0)
final[0]=1;//源点加入S当中
slength=1;//S的长度为1
inth,h1;//定义两个要用到的变量
while(slength{
h=wuqiong+1;//首先将路劲设置成最大化,这样就可以将所有的路劲比较一番而后取最小值,这个值尽量比所有的权值要大!
for(i=0;i{
if(!
final[i]&&dist[i]<=h)//依次对任意顶点进行判断是否已经加入S当中,如果没加入则判断他的路劲是否最小,取最小路劲
{
h=dist[i];
h1=i;
}
}
s[h1]=h1;//取完之后将其保存到S当中
slength++;//S的长度+1
final[h1]=1;//h1已经访问了加入到S当中,将其设为0
for(i=0;i{
if(!
final[i]&&dist[h1]+juzhen[h1*length+i]{
dist[i]=dist[h1]+juzhen[h1*length+i];
pre[i]=h1;
}
}
}
zxshuchu();//循环完毕,算法执行完毕,将最小路径输出
}
//输出函数
voidtu:
:
zxshuchu()
{
inti,pr;//循环变量I,以及目标点PR
cout<int*p=newint[length];//定义一个保存最短路径的栈
inttop;//栈顶
cout<<"所有的最短路径为↓"<for(i=1;i{
top=0;//栈顶初始化0
cout<<"到"<
";
pr=i;
while(pr!
=-1)//如果pr的前驱不为-1(即pr!
=源点)则输出pr并且将pr赋为他的前驱,为-1的话说明pr这条路径已经往回走到头
{
p[top++]=pr;
pr=pre[pr];
}
while(top!
=0)//出栈,输出上面保存的路劲
{
cout<
}
cout<}
}
//主函数
voidmain()
{
tua;
a.zengjia();//增加函数
a.bianli();//遍历
a.zxgouzao();//最小路径求解
}
实验结果如下图所示(其中0代表inf):
无向图一:
无向图二: