《数据结构与算法》实验报告 |
|||
学生姓名 |
郭茁宁 |
院(系) |
计算机科学与技术 |
学 号 |
1183710109 |
专 业 |
软件工程 |
实验时间 |
2019年12月20日(周五) |
实验地点 |
格物213室 |
实验项目 |
实验4/5:查找结构的实验比较(3学时) |
||
实验目的:将课程的基本原理、技术和方法与实际应用相结合,训练和提高学生组织、存储和处理信息的能力,以及复杂问题的数据结构设计能力和程序设计能力,培养软件设计与开发所需要的实践能力。 实验要求:灵活运用基本的数据结构和算法知识,对实际问题进行分析和抽象;结合程序设计的一般过程和方法为实际问题设计数据结构和有效算法;用高级语言对数据结构和算法进行编程实现、调试,测试其正确性和有效性。 |
|||
实验内容:BST查找结构与折半查找方法的实现与实验比较 本实验要求编写程序实现BST 存储结构的建立(插入)、删除、查找和排序算法;实现折半查找算法;比较BST查找结构与折半查找的时间性能。 1. 设计BST 的左右链存储结构,并实现BST插入(建立)、删除、查找和排序算法。 2. 实现折半查找算法。 3. 实验比较:设计并产生实验测试数据,考察比较两种查找方法的时间性能,并与理论结果进行比较。以下具体做法可作为参考: (1)第1组测试数据: n=1024个已排序的整数序列(如0至2048之间的奇数);第2组测试数据:第1组测试数据的随机序列。 (2)按上述两组序列的顺序作为输入顺序,分别建立BST。 (3)编写程序计算所建的两棵BST的查找成功和查找失败的平均查找长度(主要是改造Search算法,对“比较”进行计数),并与理论结果比较。 (4)以上述BST的中序遍历序列作为折半查找的输入,编写程序分别计算折半查找的查找成功和查找失败的平均查找长度,并与理论结果比较。 (5)以上实验能否说明:就平均性能而言,BST的查找与折半查找差不多,为什么? |
|||
数据结构定义: class BSTree:二叉搜索树类,拥有add连接、sorted输出排序数列、insert插入结点、del删除结点、find_count查找并计数等成员函数; |
|||
算法设计与分析(要求画出核心内容的程序流程图):
读入n个数后建立一棵二叉搜索树,即把n个数不断插入到已有(一开始是空树)。插入操作:
每读入一个要删除的数,就先找到该点,判断是如下哪种类型:
int find_count(int value, int cnt) { if (value == this->val) return cnt; return value < val ? (son[0] == NULL ? -cnt : son[0]->find_count(value, cnt + 1)) : (son[1] == NULL ? -cnt : son[1]->find_count(value, cnt + 1)); }
void sorted() // 打印中序遍历,排序结果 { if (son[0] != NULL) son[0]->sorted(); printf("%-4d", val); if (son[1] != NULL) son[1]->sorted(); }
int Half_Search(int x, int n, int a[]) // 折半查找 { int l = 1, r = n, mid, length = 1; bool flag = false; while (l <= r) { mid = (l + r) / 2; if (x == a[mid]) { flag = true; break; } (x < a[mid]) ? r = mid - 1 : l = mid + 1; length++; } return flag ? length : -length; }
int find_count(int value, int cnt) { if (value == this->val) return cnt; return value < val ? (son[0] == NULL ? -cnt : son[0]->find_count(value, cnt + 1)) : (son[1] == NULL ? -cnt : son[1]->find_count(value, cnt + 1)); } int Half_Search(int x, int n, int a[]) // 折半查找 { int l = 1, r = n, mid, length = 0; bool flag = false; while (l <= r) { length++; mid = (l + r) / 2; if (x == a[mid]) { flag = true; break; } (x < a[mid]) ? r = mid - 1 : l = mid + 1; } return flag ? length : -length; } 在比较中记录次数 length > 0 ? (tree_succ_times += 1, tree_succ_length += length) : (tree_fail_times += 1, tree_fail_length += length); printf("Success: %10d %8.3lf\n", tree_succ_times, 1.0 * tree_succ_length / tree_succ_times); printf("Failure: %10d %8.3lf\n", tree_fail_times, 1.0 * tree_fail_length / tree_fail_times); length > 0 ? (half_succ_times += 1, half_succ_length += length) : (half_fail_times += 1, half_fail_length += length); printf("Success: %10d %8.3lf\n", half_succ_times, 1.0 * half_succ_length / half_succ_times); printf("Failure: %10d %8.3lf\n", half_fail_times, 1.0 * half_fail_length / half_fail_times); 输出平均查找长度
通过计算1亿次查找的成功/失败查找长度/用时,比较性能 sta = clock(); for (int i = 1, x; i <= m; i++) { …… } end = clock(); printf("It takes %.4lfs totally, %.6lfus per cmp.\n", (double)(end - sta) / CLOCKS_PER_SEC, 1000.0 * (double)(end - sta) / (tree_succ_length - tree_fail_length));
|
|||
|
|||
实验测试结果及结果分析:
Tree: Success: 49999971 12.490 Failure: 50000029 -13.480 It takes 12.5780s totally, 0.009687us per cmp.
Half: Success: 49999912 9.012 Failure: 50000088 -11.002 It takes 11.7700s totally, 0.011762us per cmp.
可以看出:
结论:
|
|||
问题及解决方法:
|
|||
源程序名称:lab4.cpp |
注意:正文文字为宋体小4号,图中文字为宋体5号。行距为多倍行距1.25。
源程序与此报告打包提交,压缩包采用学号命名。
// lab4.cpp
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
using namespace std;
#define Child_Num 2
#define N 142857
#define MAX 0x7fffffff
class BSTree // 小于:左子树 大于:右子树
{
public:
int val, LD, RD, BF;
BSTree *son[Child_Num], *fa;
BSTree()
{
for (int i = 0; i < Child_Num; i++) son[i] = NULL;
fa = NULL;
BF = LD = RD = 0;
}
void add(BSTree *child, int child_num)
{
son[child_num] = child;
child->fa = this;
}
void sorted() // 打印中序遍历,排序结果
{
if (son[0] != NULL) son[0]->sorted();
printf("%-4d", val);
if (son[1] != NULL) son[1]->sorted();
}
bool leaf() { return this == NULL ? false : son[0] == NULL && son[1] == NULL; }
int height() { return max(LD, RD); }
void calcBF()
{
if (this->leaf()) { return; }
else
{
if (son[0] != NULL) son[0]->calcBF(), LD = son[0]->height() + 1;
if (son[1] != NULL) son[1]->calcBF(), RD = son[1]->height() + 1;
}
this->BF = LD - RD;
}
void insert(BSTree **head)
{
if (*head == NULL)
{
*head = this;
return;
}
for (BSTree *f1 = *head, *f2 = f1; f1 != NULL; f2 = f1)
{
f1 = this->val <= f1->val ? f1->son[0] : f1->son[1];
if (f1 == NULL) f2->add(this, this->val <= f2->val ? 0 : 1);
}
}
void del(BSTree **head)
{
if (son[0] == NULL && son[1] == NULL)
{
fa->son[0] == this ? fa->son[0] = NULL : fa->son[1] = NULL;
delete this;
return;
}
else if (son[0] != NULL && son[1] != NULL) // 左儿子最右
{
BSTree *x = son[0];
while (x->son[1] != NULL) x = x->son[1];
this->val = x->val;
if (x == son[0] && x->son[0] != NULL) { add(x->son[0], 0); }
else
x->fa->son[1] = x->son[0];
delete x;
}
else
{
if (son[1] == NULL) // 右子树为空
{
if (fa != NULL) { fa->add(son[0], this == fa->son[0] ? 0 : 1); }
else
{
son[0]->fa = NULL;
*head = son[0];
}
}
else if (son[0] == NULL) // 左子树为空
{
if (fa != NULL) { fa->add(son[1], this == fa->son[0] ? 0 : 1); }
else
{
son[1]->fa = NULL;
*head = son[1];
}
}
delete this;
}
}
int find_count(int value, int cnt)
{
if (value == this->val) return cnt;
return value < val ? (son[0] == NULL ? -cnt : son[0]->find_count(value, cnt + 1)) : (son[1] == NULL ? -cnt : son[1]->find_count(value, cnt + 1));
}
};
void Delete(BSTree *arr[], BSTree **head) // 删除节点
{
int m;
scanf("%d", &m);
for (int i = 1, x; i <= m; i++)
{
scanf("%d", &x);
if (!arr[x])
{
printf("None\n");
continue;
}
arr[x]->del(head);
(*head)->sorted();
cout << endl;
}
}
int Half_Search(int x, int n, int a[]) // 折半查找
{
int l = 1, r = n, mid, length = 1;
bool flag = false;
while (l <= r)
{
mid = (l + r) / 2;
if (x == a[mid])
{
flag = true;
break;
}
(x < a[mid]) ? r = mid - 1 : l = mid + 1;
length++;
}
return flag ? length : -length;
}
void Search(BSTree *head, int n, int a[]) // 查找节点
{
clock_t sta, end;
int m;
int tree_succ_times = 0, tree_succ_length = 0, tree_fail_times = 0, tree_fail_length = 0;
int half_succ_times = 0, half_succ_length = 0, half_fail_times = 0, half_fail_length = 0;
scanf("%d", &m);
cout << endl;
sta = clock();
for (int i = 1, x; i <= m; i++)
{
//srand((int)time(0));
x = rand() % 2048 + 1;
int length = head->find_count(x, 1);
length > 0 ? (tree_succ_times += 1, tree_succ_length += length) : (tree_fail_times += 1, tree_fail_length += length);
}
end = clock();
cout << "Tree:" << endl;
printf("Success: %10d %8.3lf\n", tree_succ_times, 1.0 * tree_succ_length / tree_succ_times);
printf("Failure: %10d %8.3lf\n", tree_fail_times, 1.0 * tree_fail_length / tree_fail_times);
printf("It takes %.4lfs totally, %.6lfus per cmp.\n", (double)(end - sta) / CLOCKS_PER_SEC, 1000.0 * (double)(end - sta) / (tree_succ_length - tree_fail_length));
cout << endl;
sta = clock();
for (int i = 1, x; i <= m; i++)
{
//srand((int)time(0));
x = rand() % 2048 + 1;
int length = Half_Search(x, n, a);
length > 0 ? (half_succ_times += 1, half_succ_length += length) : (half_fail_times += 1, half_fail_length += length);
}
end = clock();
cout << "Half:" << endl;
printf("Success: %10d %8.3lf\n", half_succ_times, 1.0 * half_succ_length / half_succ_times);
printf("Failure: %10d %8.3lf\n", half_fail_times, 1.0 * half_fail_length / half_fail_times);
printf("It takes %.4lfs totally, %.6lfus per cmp.\n", (double)(end - sta) / CLOCKS_PER_SEC, 1000.0 * (double)(end - sta) / (half_succ_length - half_fail_length));
cout << endl;
}
int main()
{
freopen("init.txt", "r", stdin);
int n, a[N];
BSTree *arr[N], *head = NULL, *t;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
t = new BSTree();
arr[a[i]] = t;
t->val = a[i];
t->insert(&head);
}
head->calcBF();
sort(a + 1, a + n + 1);
//Delete(arr, &head);
Search(head, n, a);
fclose(stdin);
return 0;
}
// create_data.cpp
#include <cstdio>
#include <cstdlib>
#define N 1024
#define M 2048
bool f[M + 5];
int main()
{
freopen("data.txt", "w", stdout);
printf("%d\n", N);
for (int i = 1; i <= N; i++)
{
int x = rand() % M + 1;
if (!f[x] && x % 2 != 0)
{
printf("%d ", x);
f[x] = true;
}
else
i--;
}
fclose(stdout);
return 0;
}
来源:CSDN
作者:頔潇
链接:https://blog.csdn.net/gzn00417/article/details/104145691