数据结构上机实验6.29
写的是真的丑,就冲着能跑而已,大概意会一下,一切为了做题服务,这周末考完试会去把图的代码敲好,为实验考试做准备
问题 C: 算法7-10,7-11:关节点和重连通分量
题目描述
假若在删去顶点v以及和v相关联的各边之后,将图的一个连通分量分割成两个或两个以上的连接分量,则称顶点v为该图的一个关节点。一个没有关节点的连通图称为重连通图。在重连通图上,任意一对顶点之间至少存在两条路径,则在删去某个顶点以及依附于该顶点的各边时也不会破坏图的连通性。
利用深度优先搜索可以求出图的关节点,并由此可以判断图是否是重连通的。
通过修改深度优先搜索遍历的算法便可以得到求关节点的算法,其算法描述如下:
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法求出所有的关节点,并输出这些关节点。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个整数,如果为1,则表示第i个顶点和第j个顶点有直接连接,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图,且保证图中只有一个连通分量
输出
第一行有一个整数x,即图中关节点的个数。
第二行输出x个整数,表示所有关节点的顶点编号,请按照编号从小到大的顺序输出。每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
4 0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0
样例输出
1 0
提示
在本题中,需要掌握图的深度优先遍历的方法,并需要掌握通过深度优先搜索求得图中关节点的算法。通过生成深度优先生成树可以得出两类关节点的特性:
1. 若生成树的根有两棵或两棵以上的子树,则此根顶点必为关节点。
2. 若生成树中某个非叶子顶点v,其某棵子树的根和子树中的其他结点均没有指向v的祖先的回边,则说明v是关节点。
注意以上两点特性,就可以成功的通过深度优先搜索遍历的算法得出图中的关节点了。
思路
本来没怎么看懂题,导致走了很多弯路,后来大佬提醒说可以删除点来找有无两个连通分量,就套用之前写的输出连通分量的代码
这里最需要注意的是在记录哪一个是关节点的时候,是记i,不是ptr,因为碰巧几个样例结果一样导致提交错误,后来改了很多次才发现
代码
#include<iostream>
using namespace std;
struct dfs{bool **edge;
};
void createdfs(int n,dfs &d){//注意这里是引用 d.edge=new bool*[n];for(int i=0;i<n;i++){d.edge[i]=new bool[n];}for(int i=0;i<n;i++){for(int j=0;j<n;j++){//cout<<i<<" "<<j;cin>>d.edge[i][j];}//cout<<d.edge[i][j];}//cout<<d.edge[0][0];
}
void outputdfs(int n,dfs d){for(int i=0;i<n;i++){for(int j=0;j<n;j++){//cout<<"Sf"<<endl;cout<<d.edge[i][j]<<" ";}cout<<endl;}
}
int getfirstver(int n,dfs& d,int ptr,int*visited){for(int i=0;i<n;i++){if(d.edge[ptr][i]==1&&visited[i]==0){d.edge[ptr][i]=0;d.edge[i][ptr]=0;return i;}}return -1;
}
int getnextver(int n,dfs &d,int w,int*visited){for(int i=0;i<n;i++){if(d.edge[w][i]==1&&visited[i]==0){//cout<<w<<" "<<i<<" "<<d.edge[w][i]<<endl;d.edge[w][i]=0;d.edge[i][w]=0;return i;}//循环的时候这个节点就过去了 }return -1;
}
void sdfs(int n,dfs &d,int *&visited,int &ptr){int w=0;visited[ptr]=1;//cout<<ptr<<" ";//<<"ptr"for(w=getfirstver(n,d,ptr,visited);w!=-1;w=getnextver(n,d,ptr,visited)){//cout<<"eaf"<<w<<endl; if(!visited[w]){//outputdfs(n,d);//cout<<endl;sdfs(n,d,visited,w);}}
}
void copydfs(dfs &x,dfs d,int n){x.edge=new bool*[n];for(int i=0;i<n;i++){x.edge[i]=new bool[n];}for(int i=0;i<n;i++){for(int j=0;j<n;j++){//cout<<i<<" "<<j;x.edge[i][j]=d.edge[i][j];}//cout<<d.edge[i][j];}
}
void dfstra(int n,dfs &d,int *&visited ,int ptr,int i,int*&c,int &temp){int count=0;dfs x;copydfs(x,d,n);for(int t=0;t<n;t++){visited[t]=0;}for(int j=0;j<n;j++){x.edge[i][j]=0;x.edge[j][i]=0;}for(ptr=0;ptr<n;ptr++){if(!visited[ptr]&&ptr!=i){ sdfs(n,x,visited,ptr);if(count==0) count++;else break;//cout<<"ptr"<<ptr;//cout<<endl;}}if(ptr<n) {//cout<<ptr<<" ";c[temp]=i;temp++;}
}
int main(){int n=0;cin>>n;dfs d;createdfs(n,d);int *c=new int[n];int temp=0;//cout<<d.edge[1][0];//outputdfs(n,d);int *visited=new int[n];/*ptr=0;dfstra(n,d,visited,ptr,0,c,temp);*/for(int i=0;i<n;i++){int ptr=0;dfstra(n,d,visited,ptr,i,c,temp);//cout<<endl;}cout<<temp<<endl;for(int j=0;j<temp;j++){cout<<c[j]<<" ";}cout<<endl;/*int c=getfirstver(n,d,1);cout<<c<<endl;*///测试找第一个邻接结点/*int a=getnextver(n,d,1);for(;a!=-1;a=getnextver(n,d,1))cout<<"a"<<a<<endl;*///测试找下一个邻接结点 return 0;
}
算法7-12:有向无环图的拓扑排序
题目描述
由某个集合上的一个偏序得到该集合上的一个全序,这个操作被称为拓扑排序。偏序和全序的定义分别如下:
若集合X上的关系R是自反的、反对称的和传递的,则称R是集合X上的偏序关系。
设R是集合X上的偏序,如果对每个x,y∈X必有xRy或yRx,则称R是集合X上的全序关系。
由偏序定义得到拓扑有序的操作便是拓扑排序。
拓扑排序的流程如下:
1. 在有向图中选一个没有前驱的顶点并且输出之;
2. 从图中删除该顶点和所有以它为尾的弧。
重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后一种情况则说明有向图中存在环。
采用邻接表存储有向图,并通过栈来暂存所有入度为零的顶点,可以描述拓扑排序的算法如下:
在本题中,读入一个有向图的邻接矩阵(即数组表示),建立有向图并按照以上描述中的算法判断此图是否有回路,如果没有回路则输出拓扑有序的顶点序列。
输入
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个整数,如果为1,则表示第i个顶点有指向第j个顶点的有向边,0表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。
输出
如果读入的有向图含有回路,请输出“ERROR”,不包括引号。
如果读入的有向图不含有回路,请按照题目描述中的算法依次输出图的拓扑有序序列,每个整数后输出一个空格。
请注意行尾输出换行
样例输入
4 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0
输出
3 0 1 2
提示
在本题中,需要严格的按照题目描述中的算法进行拓扑排序,并在排序的过程中将顶点依次储存下来,直到最终能够判定有向图中不包含回路之后,才能够进行输出。
另外,为了避免重复检测入度为零的顶点,可以通过一个栈结构维护当前处理过程中入度为零的顶点
思路
很普通的拓扑排序输出,就是记录入度,为0入栈,然后出栈检查出度
容易出问题的点是,当时为了方便,出边表是最远的离点最近,比如1的出边为4,3,2,导致不能在出栈的时候一边减去邻接结点入度,一边检验入度是否为0入栈,需要在循环外搞一下
代码
#include<iostream>
#include <cassert>
using namespace std;
struct StackNode{int data;StackNode *link;StackNode(int d = 0, StackNode *next = NULL):link(next),data(d){}
};class LinkedStack{
private:StackNode *top;
public:LinkedStack():top(NULL){}//无头结点~LinkedStack(){makeEmpty();}void Push(const int &x);bool Pop(int &x);bool getTop(int &x)const; int getSize()const;bool IsEmpty()const{return top == NULL;}bool IsFull()const{return false;}void makeEmpty();
};void LinkedStack::makeEmpty(){StackNode *p;while (top){//最后top为NULLp = top;top = top->link;delete p;}
}
void LinkedStack::Push(const int &x){top = new StackNode(x, top);assert(top);
}
bool LinkedStack::Pop(int &x){if (IsEmpty()){return false;}StackNode *p = top;top = top->link;x = p->data;delete p;return true;
}
bool LinkedStack::getTop(int &x)const{ if (IsEmpty()) return false;x = top->data; return true;
}
int LinkedStack::getSize()const{StackNode *p = top;int k = 0;while (p){p = p->link;k++;}return k;
}
struct node{int count;int data;node*next;node(int d=-1,node*link=NULL,int c=0):data(d),next(link),count(c){}
};
struct dfs{bool **edge;
};
void createdfs(int n,dfs &d){//注意这里是引用 d.edge=new bool*[n];for(int i=0;i<n;i++){d.edge[i]=new bool[n];}for(int i=0;i<n;i++){for(int j=0;j<n;j++){cin>>d.edge[i][j];}}
}
void ctreatelist(dfs d,int n,node*&p){for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(d.edge[i][j]!=0){node*newnode=new node(j);newnode->next=p[i].next;p[i].next=newnode;p[j].count++;}}}
}
void listprint(node*p,int n){node*ptr=p[0].next;for(int i=0;i<n;i++){ptr=p[i].next;cout<<i<<" :"<<ptr->count<<" ";while(ptr!=NULL){cout<<ptr->data<<" ";ptr=ptr->next;}cout<<endl;}
}
void fun(node*p,int n){LinkedStack s;int c=0,i;node*ptr;for(i=0;i<n;i++){if(p[i].count==0){s.Push(i);p[i].count=-1;}}int *k=new int[n];while(!s.IsEmpty()){s.Pop(i);k[c]=i;c++;ptr=p[i].next;p[i].count=-1;while(ptr!=NULL){p[ptr->data].count--; ptr=ptr->next;}for(i=0;i<n;i++){if(p[i].count==0){s.Push(i);p[i].count=-1;}}//listprint(p,n);}if(c<n) cout<<"ERROR"<<endl;else{for(int j=0;j<n;j++){cout<<k[j]<<" ";}cout<<endl;}
}int main(){int n=0;cin>>n;dfs d;createdfs(n,d);node*p=new node[n];ctreatelist(d,n,p);fun(p,n);return 0;
}
算法7-15:迪杰斯特拉最短路径算法
题目描述
在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。
在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。
可将迪杰斯特拉算法描述如下:
在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并按照以上描述中的算法求出源点至每一个其它顶点的最短路径长度。
输入
输入的第一行包含2个正整数n和s,表示图中共有n个顶点,且源点为s。其中n不超过50,s小于n。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。
输出
只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。
请注意行尾输出换行。
样例输入
4 1 0 3 0 1 0 0 4 0 2 0 0 0 0 0 1 0
样例输出
6 4 7
提示
在本题中,需要按照题目描述中的算法完成迪杰斯特拉算法,并在计算最短路径的过程中将每个顶点是否可达记录下来,直到求出每个可达顶点的最短路径之后,算法才能够结束。
迪杰斯特拉算法的特点是按照路径长度递增的顺序,依次添加下一条长度最短的边,从而不断构造出相应顶点的最短路径。
另外需要注意的是,在本题中为了更方便的表示顶点间的不可达状态,可以使用一个十分大的值作为标记。
思路
书上的属于比较详细的,做题的话简化一下就好,只需要记录源点到各点最短路径长度就行
循环中要注意的是已经找到最短路径的点不再重复比较
代码
#include<iostream>
using namespace std;
struct dfs{int **edge;
};
void createdfs(int n,dfs &d){//注意这里是引用 d.edge=new int*[n];for(int i=0;i<n;i++){d.edge[i]=new int[n];}for(int i=0;i<n;i++){for(int j=0;j<n;j++){//cout<<i<<" "<<j;cin>>d.edge[i][j];}//cout<<d.edge[i][j];}//cout<<d.edge[0][0];
}void fun(dfs d,int n,int s,int*dist,int*visited){for(int i=0;i<n;i++){if(d.edge[s][i]>0){dist[i]=d.edge[s][i];}else dist[i]=-1;}int k=1;int min=10000;int count=0;int temp=0;while(k!=n){k++;for(int j=0;j<n;j++){if(j!=s&&visited[j]!=1&&dist[j]!=-1){if(dist[j]<min&&dist[j]!=-1){min=dist[j];count=j;//cout<<count<<" ";}}}min=10000;visited[count]=1;//if(k!=n){for(int i=0;i<n;i++){//cout<<visited[i]<<" ";if(d.edge[count][i]>0&&visited[i]!=1){if(dist[i]==-1) dist[i]=d.edge[count][i]+dist[count];else{ temp=dist[count]+d.edge[count][i];if(temp<dist[i]) dist[i]=temp;}}//cout<<"dist[i]"<<dist[i]<<" ";} //cout<<endl; //}temp=0;}
}int main(){int n=0,s=0;cin>>n;dfs d;cin>>s;createdfs(n,d);int *dist=new int[n];int *visited=new int[n];for(int i=0;i<n;i++){dist[i]=visited[i]=0;}visited[s]=1;fun(d,n,s,dist,visited);for(int i=0;i<s;i++){cout<<dist[i]<<" ";}for(int i=s+1;i<n;i++){cout<<dist[i]<<" ";}cout<<endl;
}
算法10-2:折半插入排序
题目描述
折半插入排序同样是一种非常简单的排序方法,它的基本操作是在一个已经排好序的有序表中进行查找和插入。不难发现这个查找的过程可以十分自然的修改成折半查找的方式进行实现。
折半插入排序的算法可以描述如下:
输入
输出
样例输入
10 2 8 4 6 1 10 7 3 5 9
样例输出
1 2 3 4 5 6 7 8 9 10
提示
代码
#include<iostream>
using namespace std;
void fun(int *&a,int n){int i,j,low,high,m;for(i=2;i<=n;i++){a[0]=a[i];low=1;high=i-1;while(low<=high){m=(low+high)/2;if(a[0]<a[m]) high=m-1;else low=m+1;}if(a[2]<a[1]){a[2]=a[1];a[1]=a[0];}else{for(j=i-1;j>=high+1;j--){a[j+1]=a[j];}a[high+1]=a[0];}/* for(int j=1;j<n+1;j++){cout<<a[j]<<" ";}cout<<endl;*/}
}
int main(){int n=0;cin>>n;int*a=new int[n+1];for(int i=1;i<n+1;i++){cin>>a[i];}fun(a,n);for(int j=1;j<n+1;j++){cout<<a[j]<<" ";}cout<<endl;return 0;
}
算法10-6~10-8:快速排序
题目描述
快速排序是对起泡排序的一种改进。它的基本思想是,通过一趟排序将待排序的记录分割成两个独立的部分,其中一部分记录的关键字均比另一部分的关键字小,在分成两个部分之后则可以分别对这两个部分继续进行排序,从而使整个序列有序。
快速排序的算法可以描述如下:
输入
输出
样例输入
10 2 8 4 6 1 10 7 3 5 9
样例输出
1 2 3 4 5 6 7 8 9 10
提示
代码
#include<iostream>
using namespace std;
int partition(int*&a,int low,int high){int keyp=0;a[0]=a[low];keyp=a[low];while(low<high){while(low<high&&a[high]>=keyp)high--;a[low]=a[high];//将比关键值小的放在低端,这个时候高位空出,//但值保留,关键值在表中的原位置被覆盖 a[high]<keyp while(low<high&&a[low]<=keyp) low++;a[high]=a[low];}a[low]=a[0];return low;//==断开的位置
}
void qsort(int*&a,int low,int high){int ploc;if(low<high){ploc=partition(a,low,high);qsort(a,low,ploc-1);qsort(a,ploc+1,high);}
}
int main(){int n=0;cin>>n;int *a=new int[n+1];for(int i=1;i<=n;i++){cin>>a[i];}qsort(a,1,n);for(int j=1;j<=n;j++){cout<<a[j]<<" "; }cout<<endl;return 0;
}
算法10-12~10-14:归并排序
题目描述
归并排序是基于归并操作完成的,而一次归并操作是通过两个或两个以上的有序表合并成一个新的有序表完成的。常见的归并排序是2-路归并排序,其核心操作是将一维数组中前后相邻的两个有序序列归并成一个有序序列。其算法可以描述如下:
输入
输出
样例输入
10 2 8 4 6 1 10 7 3 5 9
样例输入
1 2 3 4 5 6 7 8 9 10
提示
在本题中,需要按照题目描述中的算法完成2-路归并排序的算法。
不难发现,2-路归并算法的时间复杂度为O(nlog2n),且需要和原始数据等数量的辅助空间。递归形式的2-路归并排序算法在形式上比较简洁,但是实用性较差。通常在需要使用归并排序的场合,往往使用非递归形式的归并排序。
与快速排序和堆排序相比,归并排序的特点在于其是一种稳定的排序方法。
代码
#include<iostream>
using namespace std;
int a[100000];
void merge(int a[],int b[],int i,int m,int n){int j,k;for(j=m+1,k=i;i<=m&&j<=n;k++){if(a[i]<a[j]) b[k]=a[i++];else b[k]=a[j++];}if(i<=m)while(k<=n&&i<=m) b[k++]=a[i++];else if(j<=n)while(k<=n&&j<=n) b[k++]=a[j++];
}
void msort(int a[],int b[],int s,int t){int m;int c[t];if(s==t) b[t]=a[s];else {m=(s+t)/2;msort(a,c,s,m);msort(a,c,m+1,t);merge(c,b,s,m,t);
}
}
int main(){int n=0;cin>>n;for(int i=1;i<n+1;i++){cin>>a[i];}msort(a,a,1,n);for(int j=1;j<n+1;j++){cout<<a[j]<<" ";}cout<<endl;return 0;
}
数据结构上机实验6.29相关推荐
- 2019级计算机学院数据结构编程作业,数据结构上机实验报告
时间:2019-05-12 08:38:58 作者:admin 数据结构实验报告 课程 数据结构 _ 院 系 专业班级 实验地点姓 名 学 号 实验时间 指导老师 数据结构上机实验报告1 一﹑实验名称 ...
- 数据结构课程设计实验验优参考(附数据结构上机实验、上机考试代码)
计算机的几个专业的数据结构考试内容有所不一样,好像上机还是什么不太一样.软件工程那边的老师还要求学会C++读取文件,后面我也会附上读取文件的相关代码,其余的实验上机.上机考试代码等等在资料区下载即可. ...
- java实验报告合肥工业大学_合肥工业大学数据结构上机实验代码与实验报告(全)github地址...
C++实现链队类--合肥工业大学数据结构实验5:链式队列 实验5 5.1 实验目的 熟练掌握队列的顺序链式存储结构. 熟练掌握队列的有关算法设计,并在链队列上实现. 根据具体给定的需求,合理设计并实现 ...
- 数据结构上机实验6.15
问题 A: 出栈合法性 题目描述 已知自然数1,2,-,N(1<=N<=100)依次入栈,请问序列C1,C2,-,CN是否为合法的出栈序列. 输入 输入包含多组测试数据. 每组测试数据的第 ...
- 《数据结构上机实验(C语言实现)》笔记(2 / 12):线性表
文章目录 验证性实验 实现顺序表各种基本运算的算法 放码 sqlist.h sqlist.cpp exp2-1.cpp 结果 实现单链表各种基本运算的算法 放码 linklist.h linklist ...
- 《数据结构上机实验(C语言实现)》笔记(1 / 12):绪论
文章目录 验证性实验 求1~n的连续整数和 说明 放码 结果 常见算法时间函数的增长趋势分析 说明 放码 结果 设计性实验 求素数个数 说明 放码 结果 求连续整数阶乘的和 说明 放码 结果 验证性实 ...
- 数据结构上机实验之串子系统
C语言实现串子系统 这个串子系统是我借鉴网上一部分人的代码,然后自己添加注释得到的,在原来的八个功能的基础上添加了一个显示字串长度的功能,所以一共九个功能. 功能分别为: 1.输入字串 2.连接字串 ...
- 数据结构上机实验-希尔排序,快速排序,堆排序
1.希尔排序 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法.该方法因DL.Shell于1959年提出而得名. ...
- JLU吉林大学21级软件数据结构上机实验(1)
第一次上机一共四道题,话不多说上题 第一题 输入格式: 输入第1行为1个正整数 n,表示当前单链表长度:第2行为 n 个空格间隔的整数,为该链表 n 个元素的数据域值.第3行为1个正整数 m,表示对该 ...
最新文章
- 全球公有云巨头:亚马逊 AWS
- 织梦DEDE后台定时分时段自动更新发布文章插件
- python基础===将Flask用于实现Mock-server
- Django从理论到实战(part50)--使用模型来处理上传的文件
- 如何绕过 TPM 2.0 安装 Windows 11 操作系统?
- java学生签到系统视频教程_手把手教你做一个Java web学生信息、选课、签到考勤、成绩管理系统附带完整源码及视频开发教程...
- html 循环_一个不被程序员认为是编程语言的语言——HTML,你怎么看?
- Java Unable to load library ‘gsdll64‘: 报错,解决方案
- vue项目 构建 打包 发布 三部曲
- 3dmax一键展uv_3Dmax批量展开场景物体的第二套UV
- ps抠图怎么放大图片_PS抠图时选区图片放大后,怎么移动图片抠图选区?
- 关于CSS中背景图片透明度问题
- Unity软件界面--Unity基本介绍
- 怎样利用python做一个软件,python可以自己做软件吗
- C语言_习题4-5 换硬币
- PWM占空比,频率,周期之间关系
- 计算机无法打开pdf文件格式,pdf格式的文件打不开 [电脑打不开pdf格式文件怎么回事]...
- visual C++ 编译器 下载
- Side Window Filtering 论文笔记
- cad指示箭头快捷键命令_cad中箭头怎么画_cad箭头画法命令 - 学无忧