2021.11.23数据结构实验课作业——查找
1、折半查找(必做题)
计算机类201和202班有80位同学,学号分别为20101-20140,20201-20240,按照学号递增顺序依次坐在1-80号座位上,请编写折半查找算法帮助老师快速找到学号为X同学,若找不到该同学则输出“找不到”,若能找到则输出其座位号以及比较次数。
2、二叉排序树(必做题)
计算机201班有40位同学,学号分别为20101-20140,若某节《数据结构》课上有2位同学旷课,其他38位同学按进入教室的时间顺序,顺序由随机函数产生。
(1)按照该顺序构造二叉排序树;
(2)若给出学号X,请输出该同学是否旷课;
3、散列表(必做题)
计算机201班有40位同学,学号分别为20101-20140,若15位同学选修某课程,使用散列函数H(key)=(key-20100)%17进行存储,并用开放定址法的线性探测法解决冲突。
(1)输出15位同学在散列表中的存储情况,输出格式为:存储位置,学号,如:
0,20117
1,20101
4、平衡二叉树(选做题1)
(1)给定一组无序整数,用平衡二叉树结构存储;
(2)给定一个查找值,实现基于平衡二叉树的查找,输出是否存在,若不存在则加入平衡二叉树中;
/*****************/
啧
我是真没想到高中时候学不会的平衡树到了大学没跑掉。。。。
推荐一篇讲平衡树的博客
线性查找(折半)
点击查看代码LineSearch.h
#pragma once
#include <iostream>
#ifndef MaxSize
#define MaxSize 100
#endif
using namespace std;
class LineSearch {
public:
LineSearch(int a[], int n); //构造函数
~LineSearch() { } //析构函数为空
int BinSearch1(int k); //折半非递归查找
int BinSearch2(int low, int high, int k); //折半递归查找
void Count() {
cout << "查找次数: " << count << endl;
};
private:
int data[MaxSize]; //查找集合为整型
int length;
int count;//查找集合的元素个数
};
LineSearch::LineSearch(int a[], int n) {
for (int i = 1; i <= n; ++i)
data[i] = a[i]; //查找集合从下标1开始存放
length = n;
count = 0;
}
int LineSearch::BinSearch1(int k) {
int mid, low = 1, high = length; //初始查找区间是[1, n]
count = 0;
while (low <= high) { //当区间存在时
++count;
mid = (low + high) / 2;
if (k < data[mid])
high = mid - 1;
else if (k > data[mid])
low = mid + 1;
else return mid; //查找成功,返回元素序号
}
return 0; //查找失败,返回0
}
int LineSearch::BinSearch2(int low, int high, int k) {
if (low > high) return 0; //递归的边界条件
else {
int mid = (low + high) / 2;
if (k < data[mid])
return BinSearch2(low, mid - 1, k);
else if (k > data[mid])
return BinSearch2(mid + 1, high, k);
else return mid; //查找成功,返回序号
}
}
二叉搜索树
点击查看代码BiSortTree.h
#pragma once
#include<iostream>
#include<cstring>
#ifndef MaxSize
#define MaxSize 100
#endif
using namespace std;
template<typename DataType>
struct BiNode
{
DataType data;
BiNode* lchild, * rchild;
};
class BiSortTree {
public:
BiSortTree(int a[], int n); //建立查找集合a[n]的二叉排序树
~BiSortTree() { Release(root); } //析构函数,同二叉链表的析构函数
void InOrder() { InOrder(root); } //中序遍历二叉树
BiNode<int>* InsertBST(int x) { return InsertBST(root, x); } //插入记录x
void DeleteBST(BiNode<int>* p, BiNode<int>* f); //删除f的左孩子p
BiNode<int>* SearchBST(int k) { return SearchBST(root, k); } //查找值为k的结点
private:
void Release(BiNode<int>* bt);
BiNode<int>* InsertBST(BiNode<int>* bt, int x);
BiNode<int>* SearchBST(BiNode<int>* bt, int k);
void InOrder(BiNode<int>* bt); //中序遍历函数调用
BiNode<int>* root; //二叉排序树的根指针
};
void BiSortTree::InOrder(BiNode<int>* bt)
{
if (bt == NULL) return;
else {
InOrder(bt->lchild);
cout << bt->data << "\t";
InOrder(bt->rchild);
}
}
BiNode<int>* BiSortTree::SearchBST(BiNode<int>* bt, int k)
{
if (bt == NULL) return NULL;
if (bt->data == k) return bt;
if (bt->data > k) return SearchBST(bt->lchild, k);
return SearchBST(bt->rchild, k);
}
BiNode<int>* BiSortTree::InsertBST(BiNode<int>* bt, int x)
{
if (bt == NULL) {
BiNode<int>* s = new BiNode<int>;
s->data = x;
s->lchild = NULL; s->rchild = NULL;
bt = s;
return bt;
}
if (bt->data > x)
bt->lchild = InsertBST(bt->lchild, x);
else bt->rchild = InsertBST(bt->rchild, x);
return bt;
}
BiSortTree::BiSortTree(int a[], int n)
{
root = NULL;
for (int i = 0; i < n; i++)
root = InsertBST(root, a[i]);
}
void BiSortTree::DeleteBST(BiNode<int>* p, BiNode<int>* f)
{
if ((p->lchild == NULL) && (p->rchild == NULL)) { //p为叶子
f->lchild = NULL; delete p; return;
}
if (p->rchild == NULL) { //p只有左子树
f->lchild = p->lchild; delete p; return;
}
if (p->lchild == NULL) { //p只有右子树
f->lchild = p->rchild; delete p; return;
}
BiNode<int>* par = p, * s = p->rchild; //p的左右子树均不空
while (s->lchild != NULL) //查找最左下结点
{
par = s;
s = s->lchild;
}
p->data = s->data;
if (par == p)
par->rchild = s->rchild; //特殊情况,p的右孩子无左子树
else par->lchild = s->rchild;
delete s;
}
void BiSortTree::Release(BiNode<int>* bt) {
if (bt == nullptr) return;
else {
Release(bt->lchild);
Release(bt->rchild);
delete bt;
}
}
点击查看代码HashTable.h
#pragma once
#include <iostream>
#ifndef MaxSize
#define MaxSize 100
#endif
using namespace std;
class HashTable {
public:
HashTable(); //构造函数,初始化空散列表
~HashTable() { }; //析构函数
int Insert(int k); //插入
int Search(int k); //查找
void Print();
private:
int H(int k); //散列函数
int ht[MaxSize]; //闭散列表
};
HashTable::HashTable() {
for (int i = 0; i < MaxSize; i++)
ht[i] = 0; // 0表示该散列单元为空
}
int HashTable::H(int k) {
return (k - 20100) % 17;
}
void HashTable::Print() {
for (int i = 0; i < MaxSize; i++)
cout << i << ' ' << ht[i] << endl;
}
int HashTable::Search(int k) {
int i, j = H(k); //计算散列地址
i = j; //设置比较的起始位置
while (ht[i] != 0)
{
if (ht[i] == k) return i; //查找成功
else i = (i + 1) % MaxSize; //向后探测一个位置
}
return -1; //查找失败
}
int HashTable::Insert(int k) {
int i, j = H(k); //计算散列地址
i = j; //设置比较的起始位置
while (ht[i] != 0)
{
if (ht[i] == k)
return -1; //原有元素k,不能插入
else i = (i + 1) % MaxSize; //向后探测一个位置
}
ht[i] = k;
return i; //返回插入位置
}
平衡二叉树
点击查看代码SelfBalancingBST.h
#pragma once
#include<iostream>
#include<cstring>
#ifndef MaxSize
#define MaxSize 100
#endif
using namespace std;
inline int max(int a, int b)
{return a > b ? a : b;}
struct SBBSTNode {
int data, height;
SBBSTNode* lchild;
SBBSTNode* rchild;
};
class SBBiSortTree {
public:
SBBiSortTree(int a[], int n); //建立查找集合a[n]的平衡二叉树
~SBBiSortTree() { Release(root); } //析构函数
void InOrder() { InOrder(root); } //中序遍历二叉树
void InsertBST(int x) { root = InsertBST(root, x); } //插入记录x
SBBSTNode* SearchBST(int k) { return SearchBST(root, k); } //查找值为k的结点
private:
void Release(SBBSTNode* bt) {
if (bt == nullptr) return;
else {
Release(bt->lchild);
Release(bt->rchild);
delete bt;
}
}
SBBSTNode* LLRotate(SBBSTNode* y);//左旋
SBBSTNode* RRRotate(SBBSTNode* y);//右旋
SBBSTNode* InsertBST(SBBSTNode* bt, int x);//插入节点
SBBSTNode* SearchBST(SBBSTNode* bt, int k);//查找值为k的节点
void InOrder(SBBSTNode* bt); //中序遍历函数调用
SBBSTNode* root; //二叉排序树的根指针
};
int Height(SBBSTNode* bt) {//求某点的高度
if (bt == NULL)
return 0;
return bt->height;
}
int GetBalance(SBBSTNode* bt) {//求某点的平衡因子
if (bt == NULL)
return 0;
return Height(bt->lchild) - Height(bt->rchild);
}
void SBBiSortTree::InOrder(SBBSTNode* bt)
{
if (bt == NULL) return;
else {
InOrder(bt->lchild);
cout << bt->data << "\t";
InOrder(bt->rchild);
}
}
SBBSTNode* SBBiSortTree::SearchBST(SBBSTNode* bt, int k)
{
if (bt == NULL) return NULL;
if (bt->data == k) return bt;
if (bt->data > k)
return SearchBST(bt->lchild, k);
return SearchBST(bt->rchild, k);
}
SBBSTNode* SBBiSortTree::InsertBST(SBBSTNode* bt, int x)
{
if (bt == NULL) {
SBBSTNode* s = new SBBSTNode;
s->data = x;
s->height = 1;
s->lchild = NULL; s->rchild = NULL;
return s;
}
if (x < bt->data)
bt->lchild = InsertBST(bt->lchild, x);
else bt->rchild = InsertBST(bt->rchild, x);
bt->height = max(Height(bt->lchild), Height(bt->rchild)) + 1;
int balance = GetBalance(bt);
if (balance > 1) {
if (x < bt->lchild->data)//LL型
return LLRotate(bt);
else {//LR型
bt->lchild = RRRotate(bt->lchild);
return LLRotate(bt);
}
}
if (balance < -1) {
if (x >= bt->rchild->data)//RR型
return RRRotate(bt);
else {//RL型
bt->rchild = LLRotate(bt->rchild);
return RRRotate(bt);
}
}
return bt;
}
SBBSTNode* SBBiSortTree::LLRotate(SBBSTNode* y) {//y为最小不平衡点
SBBSTNode* x = y->lchild;//x是y的左儿子,要变成根
y->lchild = x->rchild;
x->rchild = y;
y->height = max(Height(y->lchild), Height(y->rchild)) + 1;
x->height = max(Height(x->lchild), Height(x->rchild)) + 1;
return x;
}
SBBSTNode* SBBiSortTree::RRRotate(SBBSTNode* y) {//y是最小不平衡点
SBBSTNode* x = y->rchild;//x是y的右儿子,要变成根
y->rchild = x->lchild;
x->lchild = y;
y->height = max(Height(y->lchild), Height(y->rchild)) + 1;
x->height = max(Height(x->lchild), Height(x->rchild)) + 1;
return x;
}
SBBiSortTree::SBBiSortTree(int a[], int n)
{
root = NULL;
for (int i = 0; i < n; i++)
InsertBST(a[i]);
}
/*
585 331 837 430 221 973 155 77 193 878
*/
主函数文件
点击查看代码main.cpp
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include "LineSearch.h"
#include "BiSortTree.h"
#include "HashTable.h"
#include "SelfBalancingBST.h"
using namespace std;
void InputLin(int Stu[]) {//第一题Stu数组初始化
for (int i = 1; i <= 80; ++i)
Stu[i] = 20100 + i + (i > 40 ? 60 : 0);
return;
}
void InputBin(int Stu[]) {//第二题Stu数组初始化
for (int i = 0; i < MaxSize; ++i)
Stu[i] = 0;
srand((int)time(0));
Stu[0] = rand() % 40 + 20101;
for (int x, i = 1; i < 38; ++i)
{
x = rand() % 40 + 20101;
for (int j = 0; j < i; ++j)
{
if (Stu[j] == x)
{
x = rand() % 40 + 20101;
j = -1;
}
}
Stu[i] = x;
}
return;
}
void InputHash(int Stu[]) {//第三题Stu数组初始化
//沿用第二题所得到的随机数组作为选课的15人
/*for (int i = 1; i <= 40; ++i)
Stu[i] = 20100 + i + (i>40 ? 60 : 0);*/
return;
}
void InputSBBST(int Stu[], int n) {//第四题Stu数组初始化
srand(time(0));
for (int i = 0; i < n; ++i)
Stu[i] = rand() % 1000;
cout << endl;
return;
}
int main()
{
int Stu[MaxSize], key;//key为要查找的数值
cout << "第一题查找学号为x的学生位置" << endl;
InputLin(Stu);
LineSearch L(Stu, 80);
cout << "请输入要查找的学号" << endl;
cin >> key;
cout << "非递归查找座位号为:" << L.BinSearch1(key) << endl;
cout << "递归查找座位号为:" << L.BinSearch2(1, 80, key) << endl;
L.Count();
cout << endl;
cout << "第二题查询某学生是否旷课" << endl;
InputBin(Stu);
BiNode<int>* p = NULL;
BiSortTree B(Stu, 38);
//B.InOrder();
cout << "请输入查找的元素值" << endl;
cin >> key;
p = B.SearchBST(key);
if (p != NULL)
cout << "该同学未旷课" << endl;
else cout << "该同学旷课" << endl;
cout << endl;
delete p;
cout << "第三题15名学生选课,输出散列表中存储状态" << endl;
InputHash(Stu);
HashTable H;
for (int i = 1; i <= 15; ++i)
H.Insert(Stu[i]);
for (int x, i = 1; i <= 15; ++i) {
x = H.Search(Stu[i]);
if (x != -1)
cout << "存储位置:" << x << " 学号: " << Stu[i] << endl;
}
cout << endl;
//使用1~1000随机数
cout << "第四题输入n个随机数插入平衡树,再查询某个数字是否存在" << endl;
int n, m;//随机数个数, 查询次数
cout << "请输入随机数个数: ";
cin >> n;
InputSBBST(Stu, n);
SBBiSortTree SBB(Stu, n);
SBBSTNode* q = NULL;
SBB.InOrder();
cout << endl << "请输入查询次数: ";
cin >> m;
for (int i = 0; i < m; ++i) {
cout << "请输入查询值: ";
cin >> key;
q = SBB.SearchBST(key);
if (q == NULL) {
SBB.InsertBST(key);
cout << "该值不存在,已经加入平衡二叉树" << endl;
}
else cout << "存在" << endl;
}
delete q;
system("pause");
return 0;
}