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;
}