- 实验目的及要求
目的:通过设计一个《个人电话号码查询系统》,进一步熟悉一些二叉树的概念、以及基本知识和技能,利用所学的基本知识和技能解决简单的面向对象的程序设计问题。实现根据用户输入的信息进行快速的查询。
要求: 实现一个简单的个人电话号码查询系统,根据用户输入的信息(例如姓名等),对数据进行二叉排序并实现平衡二叉树,对数据进行快速查询。编程完成通讯录的一般性管理工作,如通讯录中记录的增加、修改、查找、删除、输出等功能。每个记录包含姓名、电话号码、住址等个人基本信息。
(1)在外存上,用文件保存电话号码信息;
(2)在内存中,设计数据结构存储电话号码信息;
(3)提供查询功能,如根据姓名实现快速查询;
(4)提供其他维护功能,例如插入、删除、修改等。
- 实验步骤
1.实验问题分析
需要用到数据结构课上学到的平衡二叉树的知识,实现删除和插入,增加功能。理解关于二叉树的相关的基本算法。将输入的信息保存入文件和从文件输出。
2.实验概要分析
1.用结构体存储联系人的信息;
2.初始化二叉树;
3.记录结点的高度,并解决结点不平衡问题;
4.实现增加联系人,查询功能;
5.主函数。
- 实验内容
代码的实现如下:
#include <stdio.h>
#include <stdlib.h>
struct stu_num
{
char stu_name[30];//姓名
int num;//电话
int number;//编号
};
//定义一个二叉树的结构体
typedef struct person_list
{
struct person_list *lchild;//左孩子
struct person_list *rchild;//右孩子
int height;
struct stu_num perfor_info;//结构体类型的数据
}person_node;
//初始化二叉树
person_node *request_person_node(const struct stu_num *value)
{
person_node *new_node;
new_node = malloc(sizeof(person_node));
if (new_node == NULL)
{
perror("未申请到二叉树节点\n");
return NULL;
}
if (value != NULL)
{
new_node->perfor_info = *value;
new_node->lchild = NULL;
new_node->rchild = NULL;
}
return new_node;
}
//记录节点的高度
#define MAX(A, B) ((A)>(B)?(A):(B))
int get_tree_height(person_node *root)
{
if(root == NULL)
return 0;
return MAX(get_tree_height(root->lchild), get_tree_height(root->rchild))+1;
}
//解决左左不平衡
person_node *tree_node_rotate_right(person_node *root)
{
person_node *tmp;
tmp = root->lchild;
root->lchild = tmp->rchild;
tmp->rchild = root;
tmp->height = get_tree_height(tmp);
root->height = get_tree_height(root);
return tmp;//返回新的root的地址给调用这个函数的用户,用于更新新的root地址
}
//解决右右不平衡
person_node *tree_node_rotate_left(person_node *root)
{
person_node *tmp;
tmp = root->rchild;
root->rchild = tmp->lchild;
tmp->lchild = root;
tmp->height = get_tree_height(tmp);
root->height = get_tree_height(root);
return tmp;
}
//解决左右不平衡
person_node *tree_node_rotate_left_right(person_node *root)
{
root->lchild = tree_node_rotate_left(root->lchild);
root = tree_node_rotate_right(root);
return root;
}
//解决右左不平衡
person_node *tree_node_rotate_right_left(person_node *root)
{
root->rchild = tree_node_rotate_right(root->rchild);
root = tree_node_rotate_left(root);
return root;
}
//增加插入个人电话信息
person_node *insert_node_to_tree(person_node *root,person_node *new_node)
{
if (root == NULL)
return new_node;
if(root ->perfor_info.number > new_node->perfor_info.number)
{
root->lchild = insert_node_to_tree(root->lchild,new_node);
}
else
{
root->rchild = insert_node_to_tree(root->rchild,new_node);
}
if(get_tree_height(root->lchild)-get_tree_height(root->rchild) == 2)//左不平衡
{
//如果插入的数据比跟的左树节点的数据要小,那他肯定是插入到root->lchild的左边去,出现了左左不平衡
if(new_node->perfor_info.number < root->lchild->perfor_info.number)//左左不平衡
{
root = tree_node_rotate_right(root);
}
else//否则则是插入到root->lchild的右边去,出现了左右不平衡
{
root = tree_node_rotate_left_right(root);
}
}
else if(get_tree_height(root->rchild)-get_tree_height(root->lchild) == 2)//右不平衡
{
if( new_node->perfor_info.number >= root->rchild->perfor_info.number)//右右不平衡
{
printf("出现右不平衡\n");
root = tree_node_rotate_left(root);
}
else//右左不平衡
{
root = tree_node_rotate_right_left(root);
}
}
root->height = get_tree_height(root);
return root;
}
//搜索查询个人电话信息
person_node *find_tree_node(person_node *root,int input_value)
{
if (root == NULL)
return NULL;
if (root->perfor_info.number > input_value)
{
return find_tree_node(root ->lchild,input_value);
}
else if (root->perfor_info.number < input_value)
{
return find_tree_node(root ->rchild,input_value);
}
return root;
}
//中序遍历打印所有电话信息
void tree_for_each(person_node *root)
{
if (root == NULL)
{
return;
}
tree_for_each(root->lchild);
printf("编号:%d,名字:%s,电话号码:%d\n",root->perfor_info.number,root->perfor_info.stu_name,root->perfor_info.num);
tree_for_each(root->rchild);
}
int main(void)
{
int choose,input_value,a;
struct stu_num input_person_data;//定义一个结构体类型的数据用来缓存联系人数据
person_node *root = NULL,*new_node,*find_node;
//初始化一个节点root为空
while(1)
{
printf("****输入数字选择相应的指令****\n");
printf("****1.添加联系人**************\n");
printf("****2.查找联系人**************\n");
printf("****3.输出所有联系人**********\n");
printf("****4.退出本系统**************\n");
printf("******************************\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
printf("请输入联系人编号:\n");
scanf("%d",&input_person_data.number);
printf("请输入联系人的姓名:\n");
scanf("%s",input_person_data.stu_name);
printf("请输入联系人的电话号码:\n");
scanf("%d",&input_person_data.num);
new_node = request_person_node(&input_person_data);
root = insert_node_to_tree(root,new_node);
break;
case 2:
printf("请输入联系人的编号查询信息\n");
scanf("%d",&input_value);
find_node = find_tree_node(root,input_value);
if (find_node == NULL)
{
printf("找不到该联系人的信息\n");
break;
}
printf("编号:%d, 姓名:%s, 电话号码:%d\n",find_node->perfor_info.number,find_node->perfor_info.stu_name,find_node->perfor_info.num);
break;
case 3:
printf("所有联系人的信息为:\n");
tree_for_each(root);
break;
case 4:
goto log_out;
}
}
return 0;
log_out:
return 0;
}
4.实验结果
5. 实验总结分析
通过这次实验,体会到要掌握以下几点内容:
1.要学会先做好模块,从大到小,进行细化。
2.编写好函数,并进行测试与调试。
3.写程序时要善于使用库函数,可以提高效率。
4.定义函数时,应选好参数的个数和数据类型。
但仍需进一步的学习二叉树地相关知识,才能够更加熟练的运用数据结构(C++)来设计系统。