数据结构实验--搜索效率比较

一、课程设计题目与要求

【问题描述】
生成N个整数序列,序列分为两组:顺序序列和随机序列,在其中搜索最大的n个数。
对顺序序列采用顺序搜索、折半搜索、二叉排序树、平衡二叉排序树进行搜索;
对随机序列采用顺序搜索、二叉排序树、平衡二叉排序树进行搜索。
其中N=500,1000,2000,5000,10000,20000,30000,50000。n=N/100

要求:
(1)分析最坏情况下不同搜索算法的复杂度;
(2)统计分析并比较不同搜索算法在N取值不同时的性能,完成以下三个方面:

对每个测试数据集,统计计算不同搜索算法搜索成功的ASL;
对每个测试数据集运行多次获得不同搜索算法的运行时间的平均值;
绘制算法实际运行结果(ASL和运行时间)的曲线图,验证和理论分析的时间复杂度的吻合性。

二、需求分析

对于不同数据序列,我们都有多种方法来搜索,合适的算法可以节约大量时间和空间的开销,如何判断最高效的方法尤为重要。

程序通过对不同大小的随机和顺序序列用顺序搜索、折半搜索、二叉搜索树搜索、平衡二叉搜索树搜索。分析不同算法的平均运行时间,得到不同大小,不同顺序下最优的搜索方法。

三、设计

3.1 设计思想

在这里插入图片描述

(1)数据结构设计

两个动态数组AB大小为用户输入的数据,分别用来存储无序和有序序列。
两个二叉搜索树,一个用无序序列构建,另一个用有序序列构建。
类似的还有两个平衡二叉搜索树,一个用无序序列构建,另一个用有序序列构建。
还有一些数组用来存储搜索到的值以及中间结果。

(2)算法设计

在这里插入图片描述

3.2 详细设计

首先是两种树的设计:

二叉搜索树:
由二叉树的递归定义性质,二叉排序树的查找同样可以使用如下递归算法查找。
如果树是空的,则查找结束,无匹配。
如果被查找的值和根结点的值相等,查找成功。否则就在子树中继续查找。如果被查找的值小于根结点的值就选择左子树,大于根结点的值就选择右子树。
二叉排序的插入是建立在二叉排序的查找之上的,插入一个结点,就是通过查找发现该结点合适插入位置,把结点直接放进去。 其实一步步构造二叉排序树的过程中就是结点插入过程。二叉排序树插入规则如下:若查找的key已经有在树中,则p指向该数据结点。若查找的key没有在树中,则p指向查找路径上最后一个结点。

平衡二叉搜索树
在构造二叉排序树的时候,每当插入一个节点时,先检查是否因插入节点而破坏了树的平衡性,如果是,则找出其中最小不平衡子树,在保持排序树的前提下,调整最小不平衡子树中各节点之间的连接关系,以达到新的平衡,其中最小平衡子树是指:离插入节点最近,且平衡因子绝对值大于1的节点作为根节点的子树。

调整最小不平衡子树一般有四种情况:

  • 单向右旋(LL型):
    插入位置为左子树的左子树,以左子树为轴心,进行单次向右旋转,如下图所示。节点旁边的数字为该节点的平衡因子,I节点为当前插入节点(如果I节点处于正中,则表示I节点既可以是左孩子也可以是右孩子。
  • 单向左旋(RR型): 插入位置为右子树的右子树,右子树为轴心,进行单次向左旋转
  • 双向旋转先左后右(LR型):插入位置为左子树的右子树,要进行两次旋转,先向左旋转,再向右旋转。
  • 双向旋转先右后左(RL型):插入位置为右子树的左子树,进行两次调整,先右旋转再左旋转;处理情况与LR类似。
    平衡因子与类型有很大的关系,需要以离插入节点最近且平衡因子绝对值>1的节点作为根节点的子树进行判定是哪种类型。

生成序列MakeRandT的设计:由于序列长度N,和两种数据序列已经被定义为全局变量与函数故此函数不需要参数,每次创建随机序列中的值的范围设定在100 * N到1000 * N之间。

创建无序序列A的方法:

srand((unsigned)time(NULL));
for (int i = 0; i < N; i++) {
		A[i] = rand() / (double)RAND_MAX * (Max - Min) + Min;
		B[i] = A[i];
	}

此时B和A完全一样,然后只需对B进行排序即可获得与A对应的有序序列,这里为了方便直接利用Sort函数进行排序。然后两个序列就生成完毕。

统计程序运行时间:用time.h里面的clock函数,在main函数中分别在每个搜索语句开始和结尾统计运行时间,并保存在time[]数组内。
start = clock();。。。。
finish = clock();
timt[i] = (double)(finish - start) / CLOCKS_PER_SEC;

程序中涉及到的搜索结果:
►有/无序序列顺序搜索:搜索到的结果为前n大的元素在序列数组中的位置(下标)分别存在M1、M2中。
►对无序序列二叉(折半)搜索:搜索到的结果为前n大的元素在序列数组中的位置(下标)存在S中
►对有/无序序列用二叉搜索树搜索:分别先把对于序列建树T1、T2,搜索结果不保存
►对有/无序序列用平衡二叉搜索树搜索:分别先把对于序列建树AVLTree1、AVLTree2,搜索结果不保存。

四、用户手册:

打开程序后会自动显示输入长度,输入待搜索序列的长度后按回车,系统会不断显示当前搜索算法搜索到的值,待所有算法均结束后,系统自动清屏,然后显示各个算法所用时间。
每次输入不同的长度,统计每个长度对应的各种搜索算法的时间,绘制图表,与理论情况对比。

五、测试数据及测试结果:

测试输入:5000
在这里插入图片描述
测试输入:10000
在这里插入图片描述

测试输入:20000
在这里插入图片描述

测试输入:30000
在这里插入图片描述

测试输入:50000
在这里插入图片描述

将得到的数据整理成表格:
在这里插入图片描述

由此做出的搜索时间与搜索数量的折线图为:
在这里插入图片描述
在这里插入图片描述

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

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

在这里插入图片描述

用以上图表和已知的不同搜索算法的ASL做对比,发现上述图像在一定程度上符合规律,这说明本程序有一定的可靠性但仍有较大的改进空间。

posted @ 2022-03-05 15:59  Cheney822  阅读(54)  评论(0编辑  收藏  举报