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;
}
posted @ 2021-12-23 14:45  快乐永恒  阅读(157)  评论(0编辑  收藏  举报