一、实验目的
查找和排序都是数据结构中非常重要的操作。查找分为静态查找、动态查找及哈希表查找等。排序的方法多种多样,并没有绝对的优劣,在具体的应用中应合理取舍。可以按照不同的标准进行分类对比学习,更为深刻全面的理解各种排序算法。
本实验内容旨在培养在实际问题中应用各种查找算法进行查找的能力及应用各种排序算法对记录集合进行排序的能力。
(1)掌握静态表的查找(如有序表的折半查找)。
(2)掌握动态查找表(如二叉排序树)。
(3)掌握哈希表的建立、查找、删除和插入算法。
(4)掌握插入类排序算法,如直接插入排序、希尔排序。
(5)掌握交换类排序算法,如冒泡排序、快速排序。
(6)掌握选择类排序算法,如简单选择排序、堆排序。
(7)掌握归并排序算法。
(8)理解基数排序算法思想。
(9)尝试改进已有排序算法。
二、实验环境(实验设备)
硬件: 微型计算机P4
软件: Windows 7 + Microsoft Visual Studio2019
三、实验内容(包括题目和要求、源码、运行结果截图等)
1. 查找与排序实验(1)——查找
题目1:输出二叉排序树中所有的关键字值不小于key的元素值
实验要求:
- 实现一个函数模板InOrderHelp大到小输出以r为根的二叉排序树中所有的关键字值不小于key的元素值。输出时,各关键字之间隔一个空格;
- 利用编程模板中提供的主函数,测试算法正确性。
源码:
template <class ElemType, class KeyType>
void InOrderHelp(BinTreeNode<ElemType>* r, const KeyType& key)
// 操作结果: 从大到小输出以r为根的二叉排序树中所有的关键字值不小于key的元素值。输出时,各关键字之间隔一个空格
{
if (r != nullptr) {
InOrderHelp(r->rightChild, key);
if (r->data >= key)cout << r->data << " ";
InOrderHelp(r->leftChild, key);
}
else return;
}
template <class ElemType, class KeyType>
void InOrder(const BinarySortTree<ElemType, KeyType> &t, const KeyType & key)
// 操作结果: 从大到小输出二叉排序树中所有的关键字值不小于key的元素值
{
InOrderHelp((BinTreeNode<ElemType> *)t.GetRoot(), key);
}
运行结果截图:
题目3:链地址法处理冲突的哈希表
实验要求:
- 编程模板中给出了链地址法处理冲突的哈希表类模板MyHashTable,请补全所缺少的插入函数Insert,新结点插入在单链表尾部。
- 利用编程模板中提供的主函数,测试插入和删除函数的正确性。
源码:
template <class ElemType, class KeyType>
bool MyHashTable<ElemType, KeyType>::Insert(const ElemType &e)
// 操作结果: 在散列表中插入数据元素e,插入成功返回true,否则返回false
{
int index = e % m;
ht[index].Insert(ht[index].Length() + 1, e);
return 1;
}
运行结果截图:
2. 查找与排序实验(2)——排序
题目1:折半插入排序
实验要求:
- 实现一个函数模板BInsertSort,实现折半插入排序算法。折半插入排序是指使用有序表的折半查找算法确定各元素的插入位置。
- 利用编程模板中提供的主函数中测试算法正确性。
源码:
template<class ElemType>
void ShowRunK(ElemType elem[], int n, int k)
// 操作结果: 显示数组elem的各数据元素值
{
cout << "第" << setw(2) << k << "趟排序结果:";
for (int i = 0; i < n; i++)
{
cout << setw(2) << elem[i] << " ";
}
cout << endl;
}
template <class ElemType>
void BInsertSort(ElemType elem[], int n)
// 操作结果: 实现折半插入排序
{
for (int i = 1; i < n; i++) {
int temp = elem[i];
int j;
for (j = i - 1; j >= 0; j--) {
if (elem[j] > temp) {
elem[j + 1] = elem[j];
}
else {
break;
}
}
elem[j + 1] = temp;
ShowRunK(elem, n, i);
}
}
运行结果截图:
题目2: 改进冒泡排序
实验要求:
- 实现一个函数模板MyBubbleSort,对教材上的冒泡排序算法进行改进,当某一趟排序没有发生交换时则不用执行下一趟。
- 利用编程模板中提供的主函数,测试算法正确性。
源码:
template<class ElemType>
void ShowRunK(ElemType elem[], int n, int k)
// 操作结果: 显示数组elem的各数据元素值
{
cout << "第" << setw(2) << k << "趟排序结果:";
for (int i = 0; i < n; i++)
{
cout << setw(2) << elem[i] << " ";
}
cout << endl;
}
template <class ElemType>
void MyBubbleSort(ElemType elem[], int n)
// 操作结果:在数组elem中用冒泡排序进行排序
{
for (int i = 1; i < n; i++) {
int k = 0;
for (int j = 0; j < n - i; j++) {
if (elem[j] > elem[j + 1]) {
k = 1;
ElemType temp = elem[j];
elem[j] = elem[j + 1];
elem[j + 1] = temp;
}
}
ShowRunK(elem, n, i);
if (k == 0) {
break;
}
}
}
运行结果截图:
题目3:以单链表为存储结构的简单选择排序
实验要求:
- 实现一个函数模板SelectSort,以带头结点的单链表为存储结构实现简单选择排序
- 利用编程模板中提供的主函数,测试算法正确性。
源码:
template <class ElemType>
void Show(const ElemType &e)
// 操作结果: 显示数据元素
{
cout << setw(2) << e << " ";
}
template<class ElemType>
void ShowRunK(LinkList<ElemType> &la, int k)
// 操作结果: 显示链表la的各数据元素值
{
ElemType e;
cout << "第" << setw(2) << k << "趟排序结果:";
la.Traverse(Show);
cout << endl;
}
template <class ElemType>
void SelectSort(LinkList<ElemType> &la)
// 操作结果: 以带头结点的单链表为存储结构实现简单选择排序
{
for (int i = 1; i <= la.Length(); i++) {
int minpos = i;
int minn, temp;
la.GetElem(i, minn);
for (int j = i + 1; j <= la.Length(); j++) {
la.GetElem(j, temp);
if (temp < minn) {
minpos = j;
minn = temp;
}
}
if (minpos == i) {
continue;
}
la.GetElem(i, temp);
la.SetElem(minpos, temp);
la.SetElem(i, minn);
ShowRunK(la, i);
}
}
运行结果截图:
四、实验小结(包括实验过程中遇到问题和解决方法、心得体会等)
通过学习查找与排序的实验,我学到了
1.掌握不同的查找和排序方法,并能用高级语言实现相应算法。
2熟练掌握顺序查找和二分查找方法。
3熟练掌握直接插入排序、选择排序、冒泡排序、快速排序。