实验4-树、二叉树与查找
集美大学课程实验报告-实验4-树、二叉树与查找
| 项目名称 | 内容 |
|---|---|
| 课程名称 | 数据结构 |
| 班级 | 网安2512 |
| 学号 | 202521336035 |
| 实验项目名称 | 树、二叉树与查找 |
| 上机实践日期 | 2026.05.09 |
| 上机实践时间 | 2学时 |
一、目的(本次实验所涉及并要求掌握的知识点)
- 掌握二叉树的创建、求高度等基础操作。
- 学习二叉树中序、先序、后序基本操作。
- 理解二叉树的递归结构以及相关递归算法的实现。
- 掌握二叉树层次遍历的队列实现。
- 学习二叉排序树的创建、查找、插入、删除等操作。
- 掌握哈希表的基本应用,学会解决冲突。
二、实验内容与设计思想
题目1:先序序列创建二叉树
函数相关伪代码
二叉树结构体 treenode
data 字符
lchild 左孩子指针 rchild 右孩子指针
节点初始化
//时间复杂度为O(1)
先序创建二叉树函数 maketree(先序字符串s,索引index)
if(index>=字符串长度)
return nullptr
取出字符x=s[index],index自增1
if(x=='#') //空节点
return nullptr
创建新节点root,值为x
root->lchild=maketree(s,index) //递归构建左子树
root->rchild=maketree(s,index) //递归构建右子树
return root
//时间复杂度为O(n)
中序遍历函数 inOrder(根节点root)
if(root!=NULL)
inOrder(root->lchild)
输出data+空格
inOrder(root->rchild)
//时间复杂度为O(n)
函数代码
struct treenode {
char data;
treenode* lchild;
treenode* rchild;
treenode(char x) :data(x), lchild(nullptr), rchild(nullptr) {}
};
treenode* maketree(string& s, int& index) {
if (index >= s.size()) {
return nullptr;
}
char x = s[index++];
if (x == '#') {
return nullptr;
}
treenode* root = new treenode(x);
root->lchild = maketree(s, index);
root->rchild = maketree(s, index);
return root;
}
void inOrder(treenode* root)
{
if (root != NULL)
{
inOrder(root->lchild);
cout << root->data << " ";
inOrder(root->rchild);
}
}
题目2:先序输出叶结点
函数相关伪代码
PreorderPrintLeaves(二叉树BT)
if(BT==NULL)
return
//判断是否为叶子节点(无左右孩子)
if(BT->Left==NULL&&BT->Right==NULL)
输出空格+data
PreorderPrintLeaves(BT->Left) //遍历左子树
PreorderPrintLeaves(BT->Right) //遍历右子树
//时间复杂度为O(n)
函数代码
void PreorderPrintLeaves(BinTree BT) {
if (BT == NULL) {
return;
}
if (BT->Left == NULL && BT->Right == NULL) {
printf(" %c", BT->Data);
}
PreorderPrintLeaves(BT->Left);
PreorderPrintLeaves(BT->Right);
}
题目3:求二叉树高度
函数相关伪代码
GetHeight(二叉树BT)
if(BT==NULL) //空树高度为0
return 0
左子树高度=GetHeight(BT->Left)
右子树高度=GetHeight(BT->Right)
// 树高 = 最大子树高度 + 1
return max(左子树高度, 右子树高度)+1
//时间复杂度为O(n)
函数代码
int GetHeight(BinTree BT) {
if (BT == NULL) {
return 0;
}
int lefth = GetHeight(BT->Left);
int righth = GetHeight(BT->Right);
return (lefth > righth ? lefth : righth) + 1;
}
题目4:二叉树层次遍历(广度优先)
函数相关伪代码
二叉树结构体 treenode
data 字符
lchild 左孩子指针 rchild 右孩子指针
节点初始化
//时间复杂度为O(1)
层序构建二叉树函数buildtree(s)
if 字符串长度<=1
return nullptr
创建节点数组nodes,长度为字符串长度
//初始化非空节点
for(int i=1;i<n;++i)
if(s[i]!='#')
nodes[i] = 新节点,值为s[i]
//建立父子关系
for(int i=1;i<n;i++)
if(nodes[i]==nullptr)
continue;
左孩子索引=2*i
右孩子索引=2*i+1 存储右孩子下标
if(左孩子索引有效)
nodes[i]->lchild=nodes[左孩子索引]
if(右孩子索引有效)
nodes[i]->rchild=nodes[右孩子索引] 连接右孩子
return nodes[1] 返回根节点
//时间复杂度为O(n)
层序遍历函数levelorder(根节点root)
if(root==nullptr)
输出 "NULL" 并换行
return
创建队列q,将root入队
首元素标记 = 真
while(队列不为空)
当前节点cur = 队首元素,出队
if(首元素标记为真)
输出data
首元素标记 = 假
else
输出空格 + data
// 左右孩子入队
if(cur->lchild!=nullptr)
入队cur->lchild
if(cur->rchild!=nullptr)
入队cur->rchild
换行
//时间复杂度为O(n)
函数代码
struct treenode {
char data;
treenode* lchild, * rchild;
treenode(char x):data(x),lchild(nullptr),rchild(nullptr){}
};
treenode* buildtree(string& s) {
if (s.size() <= 1) {
return nullptr;
}
int n = s.size();
vector<treenode*>nodes(n, nullptr);
for (int i = 0; i < n; ++i) {
if (s[i] != '#') {
nodes[i] = new treenode(s[i]);
}
}
for (int i = 0; i < n; ++i) {
if (nodes[i] == nullptr) {
continue;
}
int left = 2 * i;
int right = 2 * i + 1;
if (left < n && nodes[left] != nullptr) {
nodes[i]->lchild = nodes[left];
}
if (right < n && nodes[right] != nullptr) {
nodes[i]->rchild = nodes[right];
}
}
return(n > 1 && nodes[1] != nullptr) ? nodes[1] : nullptr;
}
void levelorder(treenode* root) {
if (root == nullptr) {
cout << "NULL" << endl;
return;
}
queue<treenode*>q;
q.push(root);
bool isfirst = true;
while (!q.empty()) {
treenode* cur = q.front();
q.pop();
if (isfirst) {
cout << cur->data;
isfirst = false;
}
else {
cout <<" " << cur->data;
}
if (cur->lchild != nullptr) {
q.push(cur->lchild);
}
if (cur->rchild != nullptr) {
q.push(cur->rchild);
}
}
cout << endl;
}
题目5:创建二叉排序树并遍历
函数相关伪代码
二叉树结构体BSTnode
data 换行
lchild,rchild 左右孩子指针
BSTree = BSTNode指针
//时间复杂度为O(1)
插入节点函数insert(t,关键字key)
if (t==nullptr)
t = 新节点,值为key,左右孩子为空
else if(key<t ->data)
insert(t->lchild, key) //插入左子树
else
insert(t->rchild, key)//插入右子树
//时间复杂度为O(logn)
二叉树创建函数maketree(t,数组num,长度n)
t = nullptr;
for (int i = 0; i < n; ++i)
InsertBST(T, num[i])
//时间复杂度为O(logn)
中序遍历函数inorder(t)
if(t!=nullptr) 递归结束条件:节点为空
inorder(t->lchild)
输出data + 空格
inorder(t->rchild)
//时间复杂度为O(n)
查找函数search(t,关键字key)
if(t==nullptr||t->data==key)
return t
else if(key<t->data)
return search(t->lchild,key) 递归查找左子树
else
return search(t->rchild,key) 递归查找右子树
//时间复杂度为O(logn)
删除节点函数1 deleteo(p)
临时指针q, s
if(p->rchild==nullptr) //无右孩子,用左孩子代替
q=p
p=p->lchild
释放 q
else if(p->lchild==nullptr) //无左孩子,用右孩子代替
q=p
p=p->rchild
释放 q
else // 左右孩子都有,找前驱节点替换
q=p
s=p->lchild
while(s->rchild!=nullptr)
q=s
s=s->rchild
p->data=s->data
if(q!=p)
q->rchild=s->lchild
else
q->lchild=s->lchild
释放 s
retrun true
//时间复杂度为O(logn)
删除节点函数2 deletew(t,关键字key)
if(t==nullptr) return false
if(key==t->data)
return deleteo(t)
else if(key<t->data)
递归删除左子树
else
递归删除右子树
//时间复杂度为O(logn)
函数代码
typedef struct BSTnode {
int data;
struct BSTnode* lchild, * rchild;
}BSTnode,*BSTtree;
void insert(BSTtree& t,int key) {
if (t == nullptr) {
t = new BSTnode;
t->data = key;
t->lchild = t->rchild = nullptr;
}
else if (key < t->data) {
insert(t->lchild, key);
}
else {
insert(t->rchild, key);
}
}
void maketree(BSTtree& t, int num[], int n) {
t = nullptr;
for (int i = 0; i < n; ++i) {
insert(t, num[i]);
}
}
void inorder(BSTtree& t) {
if (t != nullptr) {
inorder(t->lchild);
cout << t->data << " ";
inorder(t->rchild);
}
}
BSTtree search(BSTtree t, int key) {
if (t == nullptr || t->data == key) {
return t;
}
else if (key < t->data) {
return search(t->lchild, key);
}
else {
return search(t->rchild, key);
}
}
bool deleteo(BSTtree& p) {
BSTtree q, s;
if (p->rchild == nullptr) {
q = p;
p = p->lchild;
delete q;
}
else if (p->lchild == nullptr) {
q = p;
p = p->rchild;
delete q;
}
else {
q = p;
s = p->lchild;
while (s->rchild != nullptr) {
q = s;
s = s->rchild;
}
p->data = s->data;
if (q != p) {
q->rchild = s->lchild;
}
else {
q->lchild = s->lchild;
}
delete s;
}
return true;
}
bool deletew(BSTtree& t, int key) {
if (t == nullptr)return false;
if (key == t->data) {
return deleteo(t);
}
else if (key < t->data) {
return deletew(t->lchild, key);
}
else {
return deletew(t->rchild, key);
}
}
题目6:航空公司VIP客户查询
函数相关伪代码
输入n(客户数), k(最低里程)
创建哈希表flight: 键=身份证号,值=总里程
for(int i=0;i<n;++i)
输入身份证id,里程num
累加里程=max(num,k)
flight[id]=flight[id]+累加里程
输入m(查询次数)
// 处理查询
for(int i=0;i<m;++i) 循环m次查询
输入查询身份证keyid
if(keyid 存在于哈希表中)
输出flight[keyid]
else
输出"No Info"
return 0
函数代码
#include<iostream>
#include<string>
#include<unordered_map>
#include<algorithm>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
unordered_map<string, int>flight;
for (int i = 0; i < n; ++i) {
string id;
int num;
cin >> id >> num;
int add = max(num, k);
flight[id] += add;
}
int m;
cin >> m;
for (int i = 0; i < m; ++i) {
string keyid;
cin >> keyid;
if (flight.find(keyid) != flight.end()) {
cout << flight[keyid] << endl;
}
else {
cout << "No Info" << endl;
}
}
return 0;
}
三、实验使用环境(本次实验所使用的平台和相关软件)
- 操作系统:Windows 11专业版
- 编程语言:C++
- 开发工具:Visual Studio 2026
- 编译器:vs2026默认编译器、g++
四、实验步骤和调试过程(实验步骤、测试数据设计、测试结果分析)
题目1:先序序列创建二叉树
本机运行截图

PTA提交截图

题目2:先序输出叶结点
PTA运行截图

题目3:求二叉树高度
PTA提交截图

题目4:先序序列创建二叉树
本机运行截图

PTA提交截图

题目5:创建二叉排序树并遍历
本机运行截图


题目6:航空公司VIP客户查询
本机运行截图

PTA提交截图

五、实验小结(实验中遇到的问题及解决过程、实验体会和收获)
遇到的问题及解决方法:
- 问题:中序遍历二叉树未考虑到遍历结束条件。
- 解决方法:添加节点不为空的限制。
- 问题:二叉排序树删除有双孩子的节点逻辑失误,无法成功删除。
- 解决方法:翻阅课本,求助ai利用前驱节点代替删除节点。
实验体会和收获:
- 熟悉二叉树的递归结构,基本掌握递归算法的编写与应用。
- 学会使用队列实现二叉树的层次遍历。
- 理解BST中序遍历的特点,掌握增加、排序、删除等基本操作。
- 学会使用哈希表解决实际生活中的查找问题,理解哈希冲突的处理方法。
- 通过BST中删除、层次遍历的操作,锻炼了分类讨论的能力,增强了思维逻辑能力。

浙公网安备 33010602011771号