集美大学课程实验报告-实验4-树、二叉树与查找

集美大学课程实验报告-实验4-树、二叉树与查找

项目名称 内容
课程名称 数据结构
班级 网安2413
指导教师 郑如滨
学生姓名 林沁茹
学号 202421336067
实验项目名称 实验4-树、二叉树与查找
上机实践日期
上机实践时间 2学时

一、目的(本次实验所涉及并要求掌握的知识点)

以下内容请根据实际情况编写

  • 掌握二叉排序树的创建、查找、插入与删除
  • 掌握二叉树层次遍历(广度优先)
  • 掌握哈希法中链地址法的应用
  • 掌握随机数的生成

二、实验内容与设计思想

题目1:先序序列创建二叉树

函数相关伪代码

1.定义树节点的基本结构
2.创建树的基本节点
3.创建树(递归)
4.中序遍历展示树(左-父-右)
5.用getline()来接收字符串,之后开始建树

函数代码

#include<iostream>
#include<vector>
#include<string>
using namespace std;
struct BiNode {
    char k;
    struct BiNode* rchild;
    struct BiNode* lchild;
};
BiNode* Create(char k)
{
    BiNode* node = new BiNode;
    node->k = k;
    node->lchild = NULL;
    node->rchild = NULL;
    return node;
}
BiNode* buildTree(string& b, int& l) {
	if (l>=b.length() || b[l] == '#') {
		l++;
		return NULL;
	}
	BiNode* node = Create(b[l]);
	l++;
	node->lchild = buildTree(b,l);
	node->rchild = buildTree(b,l);
	return node;
}
BiNode* Showtree(BiNode* root)
{
	if (root != NULL) {
		Showtree(root->lchild);
		cout << root->k<<" ";
		Showtree(root->rchild);
	}
	return NULL;
}
int main()
{
    string b;
	int l=0;
	while(getline(cin, b)){
        l=0;
	BiNode* root=buildTree(b, l);
	Showtree(root);
        cout<<endl;
    }
	return 0;
}

时间复杂度O(n),空间复杂度O(n)

题目2:先序输出叶结点

函数相关伪代码

1.递归实现叶子结点的打印,遍历树的所有节点
2.当节点的左右孩子都为空时,即叶子节点,打印输出

函数代码

void PreorderPrintLeaves( BinTree BT ){
   if(BT!=NULL){
       if(BT->Left==NULL&&BT->Right==NULL){
     printf(" %c",BT->Data);
    }
    PreorderPrintLeaves(BT->Left);
    PreorderPrintLeaves(BT->Right);
}
}

时间复杂度O(n),空间复杂度O(n)

题目3:求二叉树高度

函数相关伪代码

1.递归实现,遍历所有节点,l来存储不断向左的高度,r来存储不断向右的高度
2.当节点为NULL时返回0,不为NULL,则判断l和r,返回高的值并加1

函数代码

int GetHeight( BinTree BT ){
    if(BT==NULL){
        return 0;
    }
    int l=GetHeight(BT->Left);
    int r=GetHeight(BT->Right);
    if(l>r){
    return l+1;
    }else{
        return r+1;
    }
}
时间复杂度O(n),空间复杂度O(n)

题目4:jmu-ds-二叉树层次遍历

函数相关伪代码

1.定义树的节点
2.创建树节点的函数
3.递归创建树,左孩子为顺序表下标中为偶数的,右孩子为顺序表下标为奇数
4.队列存储,当一个节点被输出,队列在存储此节点的左右孩子,循环实现,直到队列为空

函数代码

#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
struct tree {
	char a;
	tree* lchild;
	tree* rchild;
};
tree* Createtree(string k, int i)
{
	tree* node = new tree;
	node->a = k[i];
	node->lchild = NULL;
	node->rchild = NULL;
	return node;
}
tree* Buildtree(string k, int i)
{
	
    if (k.empty()||k.length() <=i || k[i] == '#') {
		return NULL;
	}
    tree* root =  Createtree(k,i);
    root->lchild = Buildtree(k, 2 * i);
    root->rchild = Buildtree(k, 2 * i + 1);
	return root;
}
void Showtree(tree* node)
{
	if (node == NULL) {
		cout << "NULL";
		return;
	}
	queue<tree*> q;
	q.push(node);
	int f = 1;
	while (!q.empty()) {
		tree* current = q.front();
		q.pop();
		if (f != 1) {
			cout << " ";
		}
		f = 0;
		cout << current->a;
		if (current->lchild != NULL) {
			q.push(current->lchild);
		}
		if (current->rchild != NULL) {
			q.push(current->rchild);
		}
	}
	cout << endl;
}
int main()
{
	string k;
	tree* root = NULL;
	getline(cin, k);
	root = Buildtree(k, 1);
	Showtree(root);
	return 0;
}
时间复杂度O(n),空间复杂度O(n)

题目5:创建二叉排序树并遍历

函数相关伪代码

1.定义树的节点
2.创建树节点的函数
3.递归创建树,通过i来判断是左孩子还是右孩子
4.中序遍历展示树(左-父-右),不断递归输出

函数代码

#include<iostream>
using namespace std;
struct tree {
	int a;
	tree* lchild;
	tree* rchild;
};
tree* Createtree(int k)
{
	tree* node = new tree;
	node->a = k;
	node->lchild = NULL;
	node->rchild = NULL;
	return node;
}
tree* Buildtree(tree* root, int i)
{
	if (root == NULL) {
		root = Createtree(i);
		return root;
	}
	if (i < root->a) {
		root->lchild = Buildtree(root->lchild, i);
	}
	else {
		root->rchild = Buildtree(root->rchild, i);
	}
	return root;
}
void Showtree(tree* node)
{
	if (node == NULL) {
		return;
	}
	Showtree(node->lchild);
	cout << node->a << " ";
	Showtree(node->rchild);
}
int main()
{
	int k, i;
	tree* root = NULL;
	for ( i = 0; i < 12; i++) {//题目已给要创建的树,确定了节点个数
		cin >> k;
		root = Buildtree(root, k);
	}
	Showtree(root);
	return 0;
}
时间复杂度O(n),空间复杂度O(n)

题目6:BST(二叉排序树)的查找、插入与建树与删除

函数相关伪代码

1.定义树的节点
2.创建树节点的函数
3.递归创建树,遇到-1停止建树,根据key来判断左右孩子
4.制作菜单,用switch选择选项来实行操作,do while来实现循环,直到退出
5.寻找节点函数,传递头指针root,递归实现寻找,最后要返回root
6.插入函数,对于key的判断进行递归,直到找到NULL,插入节点
7.删除函数,递归找到被删除节点,
如果左孩子为NULL,直接删除,返回其右节点,
如果右孩子为NULL,直接删除,返回其左节点,
如果左右孩子都不为NULL,找到右子树中的最左节点,把找到的最左孩子的值赋给被删除节点,删除最左孩子节点

函数代码

#include<iostream>
using namespace std;
struct tree {
	int a;
	tree* lchild;
	tree* rchild;
};
tree* menue(tree* root);
tree* Createtree(int k);
tree* Findtree(int key, tree* root);
tree* Inserttree(tree* root, int key);
tree* Deletetree(tree* root, int key);
tree* Showtree(tree* node);

tree* Createtree(int k)
{
	tree* node = new tree;
	node->a = k;
	node->lchild = NULL;
	node->rchild = NULL;
	return node;
}
tree* Findtree(int key, tree* root)
{
	if (root == NULL) {
		cout << "没有找到该节点" << endl;
		return NULL;
	}
	else if (key == root->a) {
		cout << "找到该节点" << endl;
		return root;
	}
	else if (key < root->a) {
		root->lchild = Findtree(key, root->lchild);
	}
	else {
		root->rchild=Findtree(key, root->rchild);
	}
	return root;
}
tree* Buildtree(tree* root, int key)
{
	if (root == NULL) {
		root = Createtree(key);
		return root;
	}
	if (key < root->a) {
		root->lchild = Buildtree(root->lchild, key);
	}
	else {
		root->rchild = Buildtree(root->rchild, key);
	}
	return root;
}
tree* Inserttree(tree* root, int key) {
	if (root == NULL) {
		root = Createtree(key);
		cout << "成功插入"<<endl;
		return root;
	}
	if (key < root->a) {
		root->lchild = Inserttree(root->lchild, key);
	}
	if (key > root->a) {
		root->rchild = Inserttree(root->rchild, key);
	}
	return root;
}
tree* Deletetree(tree* root, int key) 
{
	if (root == NULL) {
		cout << "没有找到该节点" << endl;
	}
	else if (key < root->a) {
		root->lchild = Deletetree(root->lchild, key);
	}
	else if (key > root->a) {
		root->rchild = Deletetree(root->rchild, key);
	}
	else {
		if (root->lchild == NULL) {
			tree* temp = root->rchild;
			delete root;
			cout << "删除成功" << endl;
			return temp;
		}
		else if (root->rchild == NULL) {
			tree* temp = root->lchild;
			delete root;
			cout << "删除成功" << endl;
			return temp;
		}
		else {
			tree* temp = root->rchild;
			while (!temp && temp->lchild != NULL) {
				temp = temp->lchild;
			}
			root->a = temp->a;
			root->rchild = Deletetree(root->rchild, temp->a);
		}
	}
	return root;
}
tree* menue(tree * root) {
		int s, key;
		do {
	    cout << "欢迎使用BST" << endl << "请选择以下功能" << endl << "1.查找" << endl << "2.插入" << endl << "3.删除" << endl <<"4.中序遍历展示树"<<endl << "5.退出程序" << endl << "请选择你要实现的功能" << endl;				cin >> s;
		switch (s) {
		case 1:
		cout << "请输入要查找的节点:";
		cin >> key;
		root = Findtree(key, root);
		break;
		case 2:
		cout << "请输入要插入的节点:";
		cin >> key;
		root = Inserttree(root, key);
		break;
		case 3:
		cout << "请输入要删除的节点:";
		cin >> key;
		root = Deletetree(root, key);
		break;
		case 4:
			root=Showtree(root);
			cout << endl;
			break;
		case 5:
		cout << "退出程序";
		break;
		default:
		cout << "输入错误,请重新输入";
		break;
		}
		} while (s != 5);

		return root;
}
tree* Showtree(tree* node)
{
	if (node == NULL) {
		return NULL;
	}
	Showtree(node->lchild);
	cout << node->a << " ";
	Showtree(node->rchild);
	return node;
}
int main()
{
	int k, i;
	tree* root = NULL;
	cout << "遇到-1停止建树" << endl;
	cin >> k;
	while(k!=-1){
		root = Buildtree(root, k);
		cin >> k;
	}
	menue(root);
	return 0;
}

时间复杂度O(n),空间复杂度O(n)

题目7:QQ账户查询

函数相关伪代码

1.定义客户的结构
2.创建客户节点函数
3.制作菜单
4.哈希函数构建,使用哈希法中的链地址法,有7个基本结构,顺序存储着链表的头节点地址,通过输入名字字符长度来实现连接
5.注册函数,输入名字和密码,随机生成账户,并输出
6.查询函数,通过输入名字和密码来查询账户号

函数代码

#include <iostream>
#include <string>
#include <vector>
#include <random>
using namespace std;
struct kehu {
	string name;
	string mima;
	int zhanghu;
	kehu* next=NULL;
};
vector<kehu*>number(7);
kehu* Createkehu(string name, string mima);
void zhuce(string name, string mima);
void menue(int n);
void chaxun(string name, string mima);
kehu* haxi(string name);

kehu* Createkehu(string name,string mima,int randomnumber) {
	kehu* p = new kehu;
	p->name = name;
	p->mima = mima;
	p->zhanghu = randomnumber;
	p->next = NULL;
	return p;
}
void menue(int n) {
	int i;
	string name, mima;
	do {
		cout << "欢迎使用QQ账户查询系统" << endl;
		cout << "1.注册" << endl;
		cout << "2.查询账户号" << endl;
		cout << "3.退出" << endl;
		cout << "请输入你的选择:";
		cin >> i;
		switch (i) {
		case 1:
			cout << "请输入用户名:";
			cin >> name;
			cout << "请输入密码:";
			cin >> mima;
			zhuce(name, mima);
			break;
		case 2:
			cout << "请输入用户名:";
			cin >> name;
			cout << "请输入密码:";
			cin >> mima;
			chaxun(name, mima);
			break;
		case 3:
			cout << "退出" << endl;
			break;
		default:
			cout << "输入错误,请重新输入" << endl;
			break;
		}
		} while (i != 3);
}
kehu* haxi(string name) {
	int h = name.length() % 7;
	return number[h];
}
void zhuce(string name,string mima) {
	kehu* p = haxi(name);
	while (p->next != NULL) {
		if (p->name == name&&p->mima==mima) {
			cout << "用户名已存在,注册失败" << endl;
			return;
		}
		p = p->next;
	}
	random_device rd;
	mt19937 gen(rd());
	uniform_int_distribution<> dis(100000, 999999);
	int randomnumber = dis(gen);
	kehu* newnumber = Createkehu(name, mima,randomnumber);
	p->next = newnumber;
	cout << "注册成功,账号为" <<randomnumber<< endl;
}
void chaxun(string name, string mima) {
	kehu* p = haxi(name);
	while (p!= NULL) {
		if (p->name == name && p->mima == mima) {
			cout << "查询成功,该用户账号为" <<p->zhanghu<< endl;
			return;
		}
		p = p->next;
	}
	cout << "查询失败,用户名或密码错误" << endl;
}
int main()
{
	int k;
	for (k = 0;k < 7;k++) {
		number[k] = new kehu;
		number[k]->next = NULL;
	}
	menue(1);
	return 0;
}
时间复杂度O(n),空间复杂度O(n)

三、实验使用环境(本次实验所使用的平台和相关软件)

以下请根据实际情况编写


四、实验步骤和调试过程(实验步骤、测试数据设计、测试结果分析)

以下请根据实际情况编写

题目1:先序序列创建二叉树

本机运行截图

PTA提交截图
![PTA提交截图]

题目2:先序输出叶结点

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]

题目3:求二叉树高度

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]

题目4: jmu-ds-二叉树层次遍历

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]

题目5:创建二叉排序树并遍历

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]

题目6:BST(二叉排序树)的查找、插入与建树与删除

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]

题目7:QQ账户查询

本机运行截图
![本机截图]

PTA提交截图
![PTA提交截图]


五、实验小结(实验中遇到的问题及解决过程、实验体会和收获)

以下请根据实际情况编写

遇到的问题及解决方法:

  1. 问题:程序崩溃找不到原因,终端崩溃
  • 解决方法:使用断点进行调试的方法。
  1. 问题:树不能返回正确节点
  • 解决方法:修改代码,断点调试。

实验体会和收获:

  • 掌握了树的应用
  • 掌握了哈希算法
  • 掌握了随机数的生成

六、附件(参考文献和相关资料)

posted @ 2025-04-30 22:37  穗和  阅读(29)  评论(0)    收藏  举报