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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章