桂 林 理 工 大 学
实 验 报 告
一、实验名称
实验9 查找
二、实验内容:
1.分别采用顺序查找、折半查找、二叉排序树、平衡二叉树、B.树和哈希表算法实现对简单的整型数组的查找功能。
源码:
#include <stdio.h>
#include <stdlib.h>
// 顺序查找
int sequentialSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i;
}
}
return -1; // 未找到
}
// 折半查找(二分查找)
int binarySearch(int arr[], int n, int target) {
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
}
else if (arr[mid] < target) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return -1; // 未找到
}
// 二叉排序树
typedef struct treeNode {
int data;
struct treeNode* left;
struct treeNode* right;
} TreeNode;
// 插入节点
TreeNode* insert(TreeNode* root, int data) {
if (root == NULL) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
if (data < root->data) {
root->left = insert(root->left, data);
}
else if (data > root->data) {
root->right = insert(root->right, data);
}
return root;
}
// 查找节点
TreeNode* search(TreeNode* root, int target) {
if (root == NULL || root->data == target) {
return root;
}
if (target < root->data) {
return search(root->left, target);
}
else {
return search(root->right, target);
}
}
// 平衡二叉树、B 树和哈希表的实现可以比较复杂,这里暂时提供以上三种算法的实现示例,可根据需求进一步扩展。
int main() {
int arr[] = { 5, 10, 15, 20, 25, 30, 35, 40 };
int n = sizeof(arr) / sizeof(arr[0]);
// 顺序查找
int target1 = 15;
int index1 = sequentialSearch(arr, n, target1);
if (index1 != -1) {
printf("顺序查找:找到 %d 在数组中的位置:%d\n", target1, index1);
}
else {
printf("顺序查找:未找到 %d\n", target1);
}
// 折半查找
int target2 = 30;
int index2 = binarySearch(arr, n, target2);
if (index2 != -1) {
printf("折半查找:找到 %d 在数组中的位置:%d\n", target2, index2);
}
else {
printf("折半查找:未找到 %d\n", target2);
}
// 二叉排序树
TreeNode* root = NULL;
for (int i = 0; i < n; i++) {
root = insert(root, arr[i]);
}
int target3 = 20;
TreeNode* result = search(root, target3);
if (result != NULL) {
printf("二叉排序树:找到 %d\n", target3);
}
else {
printf("二叉排序树:未找到 %d\n", target3);
}
return 0;
}
2.在实验2中的学生成绩管理系统使用的是链表存储,这里用二叉排序树重新组织学生数据,实现按学生姓名进行查找的功能。
源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char name[50];
int age;
struct student* left;
struct student* right;
} Student;
// 插入节点
Student* insert(Student* root, const char* name, int age) {
if (root == NULL) {
Student* newStudent = (Student*)malloc(sizeof(Student));
strcpy_s(newStudent->name, sizeof(newStudent->name), name);
newStudent->age = age;
newStudent->left = newStudent->right = NULL;
return newStudent;
}
if (strcmp(name, root->name) < 0) {
root->left = insert(root->left, name, age);
}
else {
root->right = insert(root->right, name, age);
}
return root;
}
// 查找节点
Student* search(Student* root, const char* name) {
if (root == NULL || strcmp(root->name, name) == 0) {
return root;
}
if (strcmp(name, root->name) < 0) {
return search(root->left, name);
}
else {
return search(root->right, name);
}
}
// 中序遍历二叉排序树(用于打印输出)
void inorderTraversal(Student* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("姓名:%s,年龄:%d\n", root->name, root->age);
inorderTraversal(root->right);
}
}
int main() {
Student* root = NULL;
// 插入学生数据
root = insert(root, "Alice", 20);
root = insert(root, "Bob", 22);
root = insert(root, "Cathy", 21);
root = insert(root, "David", 23);
root = insert(root, "Emily", 19);
// 查找学生数据
char searchName[50];
printf("请输入要查找的学生姓名:");
scanf_s("%s", searchName, sizeof(searchName));
Student* result = search(root, searchName);
if (result != NULL) {
printf("找到学生:姓名:%s,年龄:%d\n", result->name, result->age);
}
else {
printf("未找到该学生信息。\n");
}
// 打印所有学生数据(中序遍历)
printf("所有学生数据如下:\n");
inorderTraversal(root);
return 0;
}
3.扩充2中的查找功能,实现同时按姓名、学号进行查找。
源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char name[50];
int age;
int studentId;
struct student* left;
struct student* right;
} Student;
// 插入节点
Student* insert(Student* root, const char* name, int age, int studentId) {
if (root == NULL) {
Student* newStudent = (Student*)malloc(sizeof(Student));
strcpy_s(newStudent->name, sizeof(newStudent->name), name);
newStudent->age = age;
newStudent->studentId = studentId;
newStudent->left = newStudent->right = NULL;
return newStudent;
}
if (studentId < root->studentId) {
root->left = insert(root->left, name, age, studentId);
}
else {
root->right = insert(root->right, name, age, studentId);
}
return root;
}
// 查找节点(同时按姓名和学号进行查找)
Student* search(Student* root, const char* name, int studentId) {
if (root == NULL || (strcmp(root->name, name) == 0 && root->studentId == studentId)) {
return root;
}
if (strcmp(name, root->name) < 0 || (strcmp(name, root->name) == 0 && studentId < root->studentId)) {
return search(root->left, name, studentId);
}
else {
return search(root->right, name, studentId);
}
}
// 中序遍历二叉排序树(用于打印输出)
void inorderTraversal(Student* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("姓名:%s,年龄:%d,学号:%d\n", root->name, root->age, root->studentId);
inorderTraversal(root->right);
}
}
int main() {
Student* root = NULL;
// 插入学生数据
root = insert(root, "Alice", 20, 1001);
root = insert(root, "Bob", 22, 1002);
root = insert(root, "Cathy", 21, 1003);
root = insert(root, "David", 23, 1004);
root = insert(root, "Emily", 19, 1005);
// 查找学生数据
char searchName[50];
int searchStudentId;
printf("请输入要查找的学生姓名:");
scanf_s("%s", searchName, sizeof(searchName));
printf("请输入要查找的学生学号:");
scanf_s("%d", &searchStudentId);
Student* result = search(root, searchName, searchStudentId);
if (result != NULL) {
printf("找到学生:姓名:%s,年龄:%d,学号: %d\n", result->name, result->age, result->studentId);
}
else {
printf("未找到该学生信息。\n");
}
// 打印所有学生数据(中序遍历)
printf("所有学生数据如下:\n");
inorderTraversal(root);
return 0;
}
4.继续扩充3的查找功能,给系统“内置”种简单的查询语言,使用该查询语言可以方便地实现查询功能。首先给出该语言的语法格式:
select姓名,成绩from成绩表where成绩> 90
源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student {
char name[50];
int age;
int studentId;
int score;
struct student* left;
struct student* right;
} Student;
void inorderTraversal(Student* root);
void inorderTraversalWithCondition(Student* root, int threshold);
// 函数用于插入学生数据
// 函数用于按学号查找学生节点
// 查询语言解析与执行
void query(Student* root, const char* query) {
char query_copy[100];
strcpy(query_copy, query);
// 解析查询语句
char* select = strtok(query_copy, " ");
char* column = strtok(NULL, ",");
char* from = strtok(NULL, " ");
char* table = strtok(NULL, " ");
char* where = strtok(NULL, " ");
char* condition = strtok(NULL, " ");
if (select == NULL || column == NULL || from == NULL || table == NULL || where == NULL || condition == NULL) {
printf("查询语句格式错误。\n");
return;
}
// 提取阈值
int threshold = atoi(condition);
// 执行查询操作
printf("查询结果:\n");
inorderTraversalWithCondition(root, threshold);
}
// 中序遍历二叉排序树满足条件的节点(查询结果)
void inorderTraversalWithCondition(Student* root, int threshold) {
if (root != NULL) {
inorderTraversalWithCondition(root->left, threshold);
if (root->score > threshold) {
printf("姓名:%s,成绩:%d\n", root->name, root->score);
}
inorderTraversalWithCondition(root->right, threshold);
}
}
int main() {
Student* root = NULL;
// 插入学生数据(包括成绩)
// 查询学生成绩大于90的学生信息
query(root, "select name, score from score_table where score 95");
// 打印所有学生数据(中序遍历)
return 0;
}
阅读上面的查询语句,通过直观感觉可以猜出该语句的功能大概是选出所有成绩大于90分的学生的姓名和成绩信息。
三、心得体会:
在编写代码解决问题的过程中,我深刻体会到了对于输入的处理至关重要。无论是从用户输入的查询语句中提取信息,还是对数据的有效检索和处理,都需要对输入进行严格的验证和解析。特别是在处理复杂的查询语句时,逐个检查关键字和条件能够确保程序的稳健性和正确性。通过对输入的仔细处理,可以避免因为用户输入不规范而导致的错误,提高程序的可靠性和稳定性。因此,编程中的“查找”不仅仅局限于数据检索,更涉及到对输入信息的全面分析和处理,这种细致入微的“查找”精神,对程序的健壮性和用户体验有着重要的影响。在今后的编程工作中,我将更加注重对输入的处理,以提升代码的质量和可靠性。