都安网站建设苏州人才网
web/
2025/10/5 18:57:43/
文章来源:
都安网站建设,苏州人才网,free wordpress template,做果蔬行业的网站实验十二 图查找
一、实验目的与要求
1#xff09;掌握拓扑排序的应用#xff1b;
2#xff09;掌握查找的概念和算法#xff1b;
3#xff09;掌握查找的基本原理以及各种算法的实现#xff1b;
4#xff09;掌握查找的应用。
二、实验内容
1. 用邻接表建立一…实验十二 图查找
一、实验目的与要求
1掌握拓扑排序的应用
2掌握查找的概念和算法
3掌握查找的基本原理以及各种算法的实现
4掌握查找的应用。
二、实验内容
1. 用邻接表建立一个有向图的存储结构。利用拓扑排序算法输出该图的拓扑排序序列。 2. 0n-1中缺失的数字
一个长度为n-1的递增排序数组中的所有数字都是唯一的并且每个数字都在范围0n-1之内。在范围0n-1内的n个数字中有且只有一个数字不在该数组中请使用折半查找算法找出这个数字。
示例 1:
输入: [0,1,3]
输出: 2
示例 2:
输入: [0,1,2,3,4,5,6,7,9]
输出: 8 三、实验结果
1请将调试通过的主要源代码、输出结果粘贴在下面必要的注释、Times New Roman 5号行间距1.5倍
2简述算法步骤选画技术路线图格式如下
S1:
S2:
3请分析算法的时间复杂度。
4请将源代码必要的注释cpp文件压缩上传 题目1
1.1实验源代码
#include iostream
using namespace std;
//拓扑排序
#define MVNum 100
typedef char VerTexType;//图的邻接表存储表示
typedef struct ArcNode{int adjvex; struct ArcNode *nextarc;
}ArcNode; typedef struct VNode{ VerTexType data;ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum];typedef struct{ AdjList vertices;//邻接表 AdjList converse_vertices;//逆邻接表int vexnum, arcnum;//图的当前顶点数和边数
}ALGraph;//定义顺序栈
typedef struct{int *base;int *top;int stacksize;
}spStack;int indegree[MVNum];//存放个顶点的入度
spStack S;//初始化栈
void InitStack(spStack S){S.base new int[MVNum];if(!S.base)exit(1);S.top S.base;S.stacksize MVNum;
}//进栈
void Push(spStack S , int i){if(S.top - S.base S.stacksize){return;}*S.top i;
}//出栈
void Pop(spStack S , int i){if(S.top S.base){return;}i *--S.top;
}//判断空栈
bool StackEmpty(spStack S){if(S.top S.base){return true;}return false;
}//确定点v在G中的位置
int LocateVex(ALGraph G , VerTexType v){for(int i 0; i G.vexnum; i){if(G.vertices[i].data v){return i;}}return -1;
}//创建有向图G的邻接表、逆邻接表
int CreateUDG(ALGraph G){int i , k;cout 请输入总顶点数总边数;cin G.vexnum G.arcnum;cout endl;cout 输入点的名称 endl;for(i 0; i G.vexnum; i){cout 请输入第 (i1) 个点的名称:;cin G.vertices[i].data;G.converse_vertices[i].data G.vertices[i].data;G.vertices[i].firstarcNULL;//初始化表头结点的指针域为NULL G.converse_vertices[i].firstarcNULL;}cout endl;cout 输入边依附的顶点 endl;for(k 0; k G.arcnum;k){VerTexType v1 , v2;int i , j;cout 请输入第 (k 1) 条边依附的顶点:;cin v1 v2;i LocateVex(G, v1); j LocateVex(G, v2);//确定v1和v2在G中位置即顶点在G.vertices中的序号 ArcNode *p1new ArcNode;//生成一个新的边结点*p1 p1-adjvexj;//邻接点序号为jp1-nextarc G.vertices[i].firstarc;G.vertices[i].firstarcp1;//将新结点*p1插入顶点vi的边表头部ArcNode *p2new ArcNode;p2-adjvexi;p2-nextarc G.converse_vertices[j].firstarc;G.converse_vertices[j].firstarcp2;}return 1;
}//求入度
void FindInDegree(ALGraph G){int i , count;for(i 0 ; i G.vexnum ; i){count 0;ArcNode *p G.converse_vertices[i].firstarc;if(p){while(p){p p-nextarc;count;}}indegree[i] count;}
}//有向图G采用邻接表存储结构若G无回路则生成G的一个拓扑序列topo[]并否则ERROR
int TopologicalSort(ALGraph G , int topo[]){int i , m;FindInDegree(G);InitStack(S);for(i 0; i G.vexnum; i){if(!indegree[i]){Push(S, i); //入度为0者进栈}}m 0;//对输出顶点计数初始为0 while(!StackEmpty(S)){Pop(S, i);//将栈顶顶点vi出栈topo[m]i;//将vi保存在拓扑序列数组topo中 m;//对输出顶点计数 ArcNode *p G.vertices[i].firstarc;//p指向vi的第一个邻接点 while(p){int k p-adjvex;//vk为vi的邻接点 --indegree[k];//vi的每个邻接点的入度减1 if(indegree[k] 0){Push(S, k); //若入度减为0则入栈} p p-nextarc;//p指向顶点vi下一个邻接结点 }}if(m G.vexnum){return 0;}return 1;
}int main(){ALGraph G;CreateUDG(G);int *topo new int [G.vexnum];cout endl;cout 有向图的邻接表、逆邻接表创建完成 endl endl;if(TopologicalSort(G , topo)){cout 该有向图的拓扑有序序列为;for(int j 0 ; j G.vexnum; j){if(j ! G.vexnum - 1){cout G.vertices[topo[j]].data , ;}else{cout G.vertices[topo[j]].data endl endl;}}}else{cout 网中存在环无法进行拓扑排序 endl;}return 0;
}1.2测试用例及其输出结果
测试用例1 程序运行结果1 测试用例2 程序运行结果2 2简述算法步骤
S1构建邻接表结构。 S2构建栈并定义初始化栈、进栈、出栈、判断空栈这四个函数体。初始化栈时创建一个新的数组存放数据并令顶指针为初始位置栈空间大小为最大数。进栈时先判断是否栈满如果栈已满则直接return如果栈未满则顶指针存入数据后后置。出栈时先判断是否栈空如果栈空则直接return如果栈非空则顶指针下移一位后弹出存放的数据。判断空栈时如果顶指针和底指针相等则当前栈为空栈否则当前栈非空。 S3构建“确定节点v在邻接表中的位置”函数。主要通过for循环遍历G如果当前节点数据与目标节点v匹配则返回当前节点的位置。如果循环结束后依然未匹配则返回-1数值表示节点v不存在于有向图G中。 S4构建“创建有向图G的邻接表和逆邻接表”函数。首先需要输入总顶点数和总边数、各节点的名称、各边依附的节点信息。通过输入各节点的名称时生成邻接表和逆邻接表并将指向第一条依附该节点的边的指针置空。接着通过输入各边依附的节点信息时确定两个节点在有向图G中的位置并生成两个个临时新边界点p1和p2令p1、p2的邻接点序号分别为该边第二个节点的位置和第一个节点的位置然后令p1、p2的下一条边为另外一个节点的第一条边指针。 S4构建“求入度”函数。通过遍历节点设置临时边指针p为逆邻接表中当前遍历节点的第一条边当p非空的时候p指向其下一条边计数变量加一然后输出当前节点的入度数。 S5构建“邻接表存储结构”函数。先求出有向图G中各节点的入度然后初始化一个栈通过for循环遍历有向图G并将入度为0的节点进行进栈操作。当存入的栈非空时将顶指针指向的节点进行出栈操作并保存在拓扑序列数组中计数输出节点个数。接着再临时新建一个p指针表示当前节点的第一条边指针。当p非空时vk是vi的邻接点vi的每个邻接点入度减去1。如果vk的入度为0则将vk入栈并令p指向vi的下一个邻接节点。最后通过if条件语句判断是否有回路如果有回路则返回0否则返回1。 S6构造主函数。主要通过调用上述函数得出拓扑序列。 3分析算法的时间复杂度
拓扑排序算法的主要思想为
第一步栈S初始化累加器count初始化。
第二步扫描顶点表将没有前驱即入度为0的顶点压栈。
第三步当栈S非空时循环1vj退出栈顶元素输出vj累加器加12将顶点vj的各个邻接点的入度减13将新的入度为0的顶点入栈。
第四步if (countvertexNum) 输出有回路信息。
如果AOV网络有n个顶点e条边在拓扑排序的过程中搜索入度为零的顶点所需的时间是O(n)。在正常情况下每个顶点进一次栈出一次栈所需时间O(n)。每个顶点入度减1的运算共执行了e次。所以总的时间复杂为O(ne)。 题目2
1.1实验源代码
#include cstdio
#include iostream
using namespace std;void half(int *a,int n){int start0,endn-1;while(startend){int mid start((end-start)1); //折半查找 //a[mid]!mid时向前判断因为肯定是之前的不等引发当前a[mid]!midif(a[mid] ! mid){if(mid0 || a[mid-1]mid-1){coutendl缺失的数字是midendl;//确定mid并输出 }end mid-1;}else{start mid1;}}
}int main(){int n,i,a[10000];cout请输入你需要输入的数字数目;cinn;coutendl请输入一个递增序列;for(i0;in;i){cina[i];}half(a,n);return 0;
}1.2测试用例及其输出结果
测试用例1
n3
array【013】
程序运行结果1 测试用例2
n9
array【012345679】
程序运行结果2 2简述算法步骤
S1构造“折半查找”函数。首先设置下标值start、end和midmid即为缺失的数字的下标之后利用while循环进行查找循环。每次折半查找都要更新min的值由于该序列是隔1递增的因此查找的终止条件为a[mid]!mid。 S2构造主函数。输入需要查找的数字和已知的递增序列再通过调用half函数输出运行结果。 3分析算法的时间复杂度
折半查找判定树的构造如果当前low和high之前有奇数个元素则mid分隔后左右两部分元素个数相等。如果当前low和high之间有偶数个元素则mid分隔后左半部分比右半部分少一个元素。
在折半查找的判定树中若midlowhigh/2向下取整则对于任何一个结点因此必有右子树结点-左子树结点数0或1。当有奇数个元素时等于0有偶数个元素时等于1。所以折半查找判定数一定是平衡二叉树树的深度为[log2n]1。查找成功时所进行的关键码比较次数至多为[log2n]1查找不成功时和给定值进行比较的次数最多不超过树的深度。
综上所述折半查找的时间复杂度为O(log2n)。 【补充】请使用顺序查找算法进行时间复杂度对比分析。
【选作】使用索引顺序表查找算法进行时间复杂度、空间复杂度的对比分析。
三、实验结果
顺序查找算法
1源代码
//顺序查找算法#include cstdio#include iostreamusing namespace std;int main(){int n,a[1000],i;cout请输入n;cinn;cout请输入排序好的数组;for(i0;in;i){scanf(%d,a[i]);}int j0,loss0,flag0;while(jn){if(a[j]!j){lossj;flag;break;}j;}if(!flag){lossn;}cout缺失值为loss;return 0;}
2测试用例及其运行结果 3时间复杂度分析
最好情况一次比较就找到所要查找的元素,时间复杂度为O(1)。最差情况比较n次共有n个元素,时间复杂度为O(n)。平均情况综合两种情况顺序查找的时间复杂度为O(n)。 索引顺序表查找算法
1源代码
#include stdio.h
#define BLOCK_NUMBER 3
#define BLOCK_LENGTH 6typedef struct IndexNode
{int data; //数据int link; //指针
}IndexNode;//索引表
IndexNode indextable[BLOCK_NUMBER];//块间查找
int IndexSequlSearch(int s[], int l, IndexNode it[], int key){int i 0;while (key it[i].data i BLOCK_NUMBER){i;}if (i BLOCK_NUMBER){return -1;}else{//在块间顺序查找int j it[i].link - 1;while (key ! s[j] j l) {j;}if (key s[j]){return j 1;}else{return -1;}}
}//建立索引表
void IndexTable(int s[], int l, IndexNode indextable[]){int j 0;for (int i 0; i BLOCK_NUMBER; i){indextable[i].data s[j];indextable[i].link j;for (j; j indextable[i].link BLOCK_LENGTH j l; j){if (s[j] indextable[i].data){indextable[i].data s[j];}}}for (int i 0; i BLOCK_NUMBER; i){indextable[i].link;}
}//打印查找的数据元素以及其在线索表中的位置
void print(int searchNumber, int index){if (index -1){printf(查找元素%d\n, searchNumber);printf(查找失败\n);return;}else{printf(查找元素%d\n, searchNumber);printf(元素位置%d\n, index);return;}
}int main(){int s[18] {22,48,60,58,74,49,86,53,13,8,9,20,33,42,44,38,12,24};IndexTable(s, 18, indextable);printf(线索表);for (int i 0; i 18; i){printf(%d ,s[i]);}printf(\n);int indexNumber1 38;int index1 IndexSequlSearch(s, 18, indextable, indexNumber1);print(indexNumber1, index1);int indexNumber2 28;int index2 IndexSequlSearch(s, 18, indextable, indexNumber2);print(indexNumber2, index2);return 0;
}2测试用例及其运行结果 3时间、空间复杂度分析
算法思想
首先将n个数据元素按块有序划分为m块m ≤ n。每一块中的结点不必有序但块与块之间必须按块有序即后一块中任一元素都必须大于前一块中最大的元素然后块之间进行二分或者顺序查找块内进行顺序查找。
时间复杂度
整体算法是对顺序查找的改进介于顺序查找和二分查找之间时间复杂度为O(log2mn/m)。
空间复杂度
一般情况下为进行分块查找可以将长度为n的表均匀分成b块每块还有s个元素即b [n/s]。索引表采用顺序查找的方式则查找成功时的平均查找长度为(sb2)/2。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/87514.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!