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

项目名称 内容
课程名称 数据结构
班级 网安2511
实验项目名称 二叉树与查找
上机实践日期 2026. 4.16和2026.4.30
上机实践时间 4 学时

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

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

  • 掌握创建二叉树与树及二叉树上的基本操作
  • 熟练掌握树的递归结构及在其上的递归算法
  • 掌握二叉树的层次遍历
  • 掌握BST树上的搜索、创建与删除
  • 掌握哈希表、平衡树的应用

二、实验内容与设计思想

以下请根据实际情况编写

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

函数1CreateNode相关伪代码

函数 CreateNode(v)
    申请新结点node
    node的data = v
    node的左孩子 = NULL
    node的右孩子 = NULL
    返回 node

函数代码

BiTNode* CreateNode(char v) {
    BiTNode* node = new BiTNode;
    node->data = v;
    node->lchild = NULL;
    node->rchild = NULL;
    return node;
}

时间复杂度:
O(1)
空间复杂度:
O(1)

函数2CreateTreeByPreOrder相关伪代码

函数 CreateTreeByPreOrder(str)
    if 索引越界 then
        返回 NULL
    ch = str[当前索引]
    索引后移一位
    
    if ch == '#' then
        返回 NULL
    
    root = CreateNode(ch)
    root的左孩子 = CreateTreeByPreOrder(str)
    root的右孩子 = CreateTreeByPreOrder(str)
    返回 root

函数代码

BiTree CreateTreeByPreOrder(string str) {
    if (index >= str.length()) return NULL;
    char ch = str[index++];
    if (ch == '#') return NULL;
    BiTree root = CreateNode(ch);
    root->lchild = CreateTreeByPreOrder(str);
    root->rchild = CreateTreeByPreOrder(str);
    return root;
}

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

题目2:先序输出叶结点

函数PreorderPrintLeaves相关伪代码

函数 PreorderPrintLeaves(BT)
    if BT == NULL then
        return
    
    if BT的左孩子 == NULL AND BT的右孩子 == NULL then
        输出 " " + BT的Data
        return
    
    PreorderPrintLeaves(BT的左孩子)
    PreorderPrintLeaves(BT的右孩子)

函数代码

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

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

题目3:求二叉树高度

函数GetHeight相关伪代码

函数 GetHeight(BT)
    if BT == NULL then
        return 0
    
    leftHeight = GetHeight(BT的左孩子)
    rightHeight = GetHeight(BT的右孩子)
    
    return max(leftHeight, rightHeight) + 1

函数代码

int GetHeight(BinTree BT) {
    if (BT == NULL) return 0;
    
    int leftHeight = GetHeight(BT->Left);
    int rightHeight = GetHeight(BT->Right);
    
    return (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;
}

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

题目4:二叉树层次遍历

函数1CreateTreeFromArray相关伪代码

函数 CreateTreeFromArray(arr, n, i)
    if i >= n 或 arr[i] == '#' then
        return NULL
    
    BT = 申请新结点
    BT的Data = arr[i]
    BT的左孩子 = CreateTreeFromArray(arr, n, 2 * i)
    BT的右孩子 = CreateTreeFromArray(arr, n, 2 * i + 1)
    return BT

函数代码

BinTree CreateTreeFromArray(char arr[], int n, int i) {
    if (i >= n || arr[i] == '#') return NULL;
    
    BinTree BT = (BinTree)malloc(sizeof(struct TNode));
    BT->Data = arr[i];
    BT->Left = CreateTreeFromArray(arr, n, 2 * i);
    BT->Right = CreateTreeFromArray(arr, n, 2 * i + 1);
    return BT;
}

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

函数2LevelOrderTraverse相关伪代码

函数 LevelOrderTraverse(BT)
    if BT == NULL then
        输出 "NULL"
        return
    
    创建空队列Q
    将BT入队
    
    while 队列不为空 do
        node = 队列出队
        输出 node的Data
        
        if node的左孩子 != NULL then
            将左孩子入队
        if node的右孩子 != NULL then
            将右孩子入队
        
        if 队列不为空 then
            输出 " "
    end while

函数代码

void LevelOrderTraverse(BinTree BT) {
    if (BT == NULL) {
        printf("NULL");
        return;
    }
    
    BinTree queue[1000];
    int front = 0, rear = 0;
    
    queue[rear++] = BT;
    
    while (front < rear) {
        BinTree node = queue[front++];
        printf("%c", node->Data);
        
        if (node->Left != NULL) queue[rear++] = node->Left;
        if (node->Right != NULL) queue[rear++] = node->Right;
        
        if (front < rear) printf(" ");
    }
}

时间复杂度:
O(n)
空间复杂度:
O(w)

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

函数1InsertBST相关伪代码

函数 InsertBST(root, val)
    if root == NULL then
        创建新结点
        root的data = val
        return root
    
    if val < root的data then
        root的左孩子 = InsertBST(root的左孩子, val)
    else if val > root的data then
        root的右孩子 = InsertBST(root的右孩子, val)
    
    return root

函数代码

BSTNode* InsertBST(BSTNode* root, int val) {
    if (root == NULL) {
        BSTNode* newNode = (BSTNode*)malloc(sizeof(BSTNode));
        newNode->data = val;
        newNode->left = NULL;
        newNode->right = NULL;
        return newNode;
    }
    
    if (val < root->data) {
        root->left = InsertBST(root->left, val);
    } else if (val > root->data) {
        root->right = InsertBST(root->right, val);
    }
    return root;
}

时间复杂度:
O(log n)
空间复杂度:
O(h)

函数2InOrderTraverse相关伪代码

函数 InOrderTraverse(root)
    if root != NULL then
        InOrderTraverse(root的左孩子)
        输出 root的data
        InOrderTraverse(root的右孩子)

函数代码

void InOrderTraverse(BSTNode* root) {
    if (root == NULL) return;
    InOrderTraverse(root->left);
    printf("%d ", root->data);
    InOrderTraverse(root->right);
}

时间复杂度:
O(n)
空间复杂度:
O(h)

题目6:BST的查找、插入与删除

函数DeleteBST相关伪代码

函数 DeleteBST(root, val)
    if root == NULL then
        return NULL
    
    if val < root的data then
        root的左孩子 = DeleteBST(root的左孩子, val)
    else if val > root的data then
        root的右孩子 = DeleteBST(root的右孩子, val)
    else
        if root的左孩子 == NULL then
            temp = root的右孩子
            free(root)
            return temp
        else if root的右孩子 == NULL then
            temp = root的左孩子
            free(root)
            return temp
        else
            minNode = FindMin(root的右孩子)
            root的data = minNode的data
            root的右孩子 = DeleteBST(root的右孩子, minNode的data)
        end if
    end if
    
    return root

函数代码

BSTNode* DeleteBST(BSTNode* root, int val) {
    if (root == NULL) return NULL;
    
    if (val < root->data) {
        root->left = DeleteBST(root->left, val);
    } else if (val > root->data) {
        root->right = DeleteBST(root->right, val);
    } else {
        if (root->left == NULL) {
            BSTNode* temp = root->right;
            free(root);
            return temp;
        } else if (root->right == NULL) {
            BSTNode* temp = root->left;
            free(root);
            return temp;
        } else {
            BSTNode* minNode = FindMin(root->right);
            root->data = minNode->data;
            root->right = DeleteBST(root->right, minNode->data);
        }
    }
    return root;
}

时间复杂度:
O(h)
空间复杂度:
O(h)

题目7:航空公司VIP客户查询

函数1hash相关伪代码

函数 hash(s)
    h = 0
    for i = 0 to s的长度-1 do
        h = (h * 131 + s[i]) mod HASH_SIZE
    end for
    return h

函数代码

int hash(char* s) {
    unsigned int h = 0;
    for (int i = 0; s[i]; i++) {
        h = h * 131 + s[i];
    }
    return h % HASH_SIZE;
}

时间复杂度:
O(1)
空间复杂度:
O(1)

函数2insert相关伪代码

函数 insert(id, miles, K)
    index = hash(id)
    addMiles = (miles < K) ? K : miles
    
    p = hashTable[index]
    while p != NULL do
        if strcmp(p的id, id) == 0 then
            p的miles = p的miles + addMiles
            return
        end if
        p = p的next
    end while
    
    newNode = 创建新结点
    newNode的id = id
    newNode的miles = addMiles
    newNode的next = hashTable[index]
    hashTable[index] = newNode

函数代码

void insert(char* id, int miles, int K) {
    int h = hash(id);
    int addMiles = (miles < K) ? K : miles;
    
    Node* p = hashTable[h];
    while (p) {
        if (strcmp(p->id, id) == 0) {
            p->miles += addMiles;
            return;
        }
        p = p->next;
    }
    
    Node* newNode = (Node*)malloc(sizeof(Node));
    strcpy(newNode->id, id);
    newNode->miles = addMiles;
    newNode->next = hashTable[h];
    hashTable[h] = newNode;
}

时间复杂度:
O(1)
空间复杂度:
O(1)

函数3find相关伪代码

函数 find(id)
    index = hash(id)
    p = hashTable[index]
    
    while p != NULL do
        if strcmp(p的id, id) == 0 then
            return p的miles
        end if
        p = p的next
    end while
    
    return -1

函数代码

int find(char* id) {
    int h = hash(id);
    Node* p = hashTable[h];
    while (p) {
        if (strcmp(p->id, id) == 0) {
            return p->miles;
        }
        p = p->next;
    }
    return -1;
}

时间复杂度:
O(1)
空间复杂度:
O(1)


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

以下请根据实际情况编写

  • 操作系统:Windows 11
  • 编程语言:C++
  • 开发工具Visual Studio 2026
  • 编译器:Microsoft Visual C++

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

以下请根据实际情况编写

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

本机运行截图
a1673c1936832823a1493cd2682a30a6

PTA提交截图
0a51c3b176d88eee08b899ab6a0f7a0c

题目2:先序输出叶结点

本机运行截图
f4d7ec1d8121bb862be570b63c27a682

PTA提交截图
33ca7de074c70ec8ca9c5fe039cd2635

题目3:求二叉树的高度

本机运行截图
1d400bd1ac2c0938ec848ee2ccafdfa5

PTA提交截图
0542e32e73b86147af97df92201c39e6

题目4:二叉树层次遍历

本机运行截图
d78577899b91048d9e1a342c1a108f97

PTA提交截图
e0ed278b45e8525b24465d2b2dde5dc7

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

本机运行截图
d95e9ebc79572353e7e9d27f697e2970

题目6:BST的查找、插入与删除

本机运行截图
1691393568eeb30deaeccfb515910fa4
87cee3d4994d44c0639b71edf3f8e40f
50bbcbab48e04ab70593bf1afe4eadbb

题目7:航空公司VIP客户查询

本机运行截图
aefaf3943b09ff64f750e3bb57839c28

PTA提交截图
c646eb26e9117aaab606fd90b5e5cd20


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

以下请根据实际情况编写

遇到的问题及解决方法:

  1. 问题:递归创建二叉树时栈溢出。
    • 解决方法:递归终止条件未正确设置,确保遇到#时正确返回NULL
  2. 问题:层次遍历输出格式错误。
    • 解决方法:结点间空格处理不当,使用 if (front < rear) printf(" ") 控制最后一个结点后无空格。
  3. 问题:BST删除结点逻辑错误。
    • 解决方法:找到右子树最小值替换后,递归删除右子树中的那个最小值

实验体会和收获:

  • 掌握了中序遍历BST得到有序序列的特性。
  • 理解了二叉树递归创建和遍历的本质。

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

posted on 2026-05-08 21:20  林宸葳  阅读(2)  评论(0)    收藏  举报