手机通讯录
手机通讯录
一、目的
-掌握vector用法
-掌握链表的创建,插入,删除
-掌握哈希法的链地址法
二、实验内容与设计思想
1.顺序链表
函数相关伪代码
1.定义结构
2.制作菜单栏(switch)
3.添加的函数,一个一个添加在链表最末端,最后返回菜单
4.删除的函数,创建三个链表节点,分别表示当前节点,当前节点的前一个节点,当前节点的后一个节点,delete要删除节点,返回菜单
5.根据姓名查找的函数,从头开始遍历,直到找到,返回菜单
6.根据电话查找的函数,从头开始遍历,直到找到,返回菜单
7.显示所有人的函数,从头遍历,返回菜单
8.退出通讯录
函数代码
#include <iostream>
#include <string>
using namespace std;
struct Person
{
string name;
string phone;
struct Person* next = NULL;
};
void AddPerson(Person* root);
Person* menue(int i);
void DeletePerson(Person* root);
void FindPersonname(Person* root);
void FindPersonphone(Person* root);
void ChangePerson(Person* root);
void AllPerson(Person* root);
Person* root = new Person;
Person* menue(int i)
{
int s;
cout << "欢迎使用通讯录管理系统\n";
cout << "请选择接下来要做什么:\n1.添加联系人\n2.删除联系人\n3.通过姓名查找联系人\n4.通过电话查找联系人\n5.修改联系人\n6.显示所有联系人\n7.退出程序\n请输入对应的数字:" << endl;
cin >> s;
do{
switch (s) {
case 1:
AddPerson(root);
break;
case 2:
DeletePerson(root);
break;
case 3:
FindPersonname(root);
break;
case 4:
FindPersonphone(root);
break;
case 5:
ChangePerson(root);
break;
case 6:
AllPerson(root);
break;
case 7:
cout << "退出程序";
break;
default:
cout << "输入错误,请重新输入";
break;
}
}while (s != 7);
return root;
}
void AddPerson(Person* root) {
Person* p = new Person;
cout << "请输入姓名:";
cin >> p->name;
cout << "请输入电话:";
cin >> p->phone;
cout << "添加成功!" << endl;
Person* temp = root;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
menue(2);
}
void FindPersonname(Person* root1) {
string name;
Person* root = root1;
cout << "请输入要查找的联系人姓名:";
cin >> name;
while (root != NULL) {
if (root->name == name && root != NULL) {
cout << "姓名:" << root->name << " 电话:" << root->phone << endl;
cout << "查找成功!" << endl;
break;
}
root = root->next;
}
if (root == NULL)
cout << "查找失败!" << endl;
menue(3);
}
void FindPersonphone(Person* root1) {
string phone;
Person* root2 = root1;
cout << "请输入要查找的联系人电话:";
cin >> phone;
while (root2 != NULL) {
if (root2->phone == phone) {
cout << "姓名:" << root2->name << " 电话:" << root2->phone << endl;
cout << "查找成功!" << endl;
break;
}
root2 = root2->next;
}
if (root2 == NULL)
cout << "查找失败!" << endl;
menue(4);
}
void ChangePerson(Person* root1) {
Person* root2 = root1;
string name;
cout << "请输入要修改的联系人姓名:";
cin >> name;
cout << "请输入新的电话:";
string newPhone;
cin >> newPhone;
while (root2 != NULL) {
if (root2->name == name) {
root2->phone = newPhone;
cout << "修改成功!" << endl;
break;
}
root2 = root2->next;
}
if (root2 == NULL)
cout << "修改失败!" << endl;
menue(5);
}
void AllPerson(Person* root1) {
Person* root2 = root1->next;
cout << "所有联系人信息:" << endl;
while (root2 != NULL) {
cout << "姓名:" << root2->name << " 电话:" << root2->phone << endl;
root2 = root2->next;
}
menue(6);
}
void DeletePerson(Person* root1) {
string name;
int k = 1;
Person* root4 = root1;
Person* root2 = root;
Person* root3 = root;
cout << "请输入要删除的联系人姓名:";
cin >> name;
while (root4 != NULL) {
if (root4->name == name) {
root2 = root4->next;
delete root4;
root3->next = root2;
cout << "删除成功!" << endl;
k = 0;
break;
}
root3 = root4;
root4 = root4->next;
}
if (k == 1)
cout << "删除失败!" << endl;
menue(7);
}
int main() {
menue(1);
while (root != NULL) {
Person* temp = root;
root = root->next;
delete temp;
}
return 0;
}
2.哈希法(链地址法)
函数相关伪代码
1.定义结构
2.定义vector来存储列表头节点,使用名字的字符长度来存储,取其对于7的余数,来确定位置
3.制作菜单栏(switch)
4.先在主菜单上确定名字和电话和字符串长度,再到添加的函数,添加在m=name.length()%7的vector[m]的链表最末端,最后返回菜单
5.先在主菜单上确定名字和字符串长度,再到删除的函数,创建三个链表节点,分别表示当前节点,当前节点的前一个节点,当前节点的后一个节点,delete要删除节点,返回菜单
6.先在主菜单上确定名字和字符串长度,根据姓名查找的函数,从m=name.length()%7的vector[m]的头节点开始遍历,直到找到,返回菜单
7.显示所有人的函数,从头遍历,返回菜单
8.退出通讯录
函数代码
1.对名字长度取模
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Person
{
string name;
string phone;
struct Person* next=NULL;
};
vector<Person*> contacts(7);
void AddPerson(int m,string name,string phone);
Person* menue(int i);
void DeletePerson(int m, string name);
void FindPersonname(int m,string name);
void ChangePerson(int m, string name, string newPhone);
void AllPerson();
Person* menue(int i)
{
int s,m;
string name, newPhone,phone;
cout << "欢迎使用通讯录管理系统\n";
cout << "请选择接下来要做什么:\n1.添加联系人\n2.删除联系人\n3.通过姓名查找联系人\n4.修改联系人\n5.显示所有联系人\n6.退出程序\n请输入对应的数字:" << endl;
cin >> s;
do{
switch (s) {
case 1:
cout << "请输入姓名:";
cin >> name;
cout << "请输入电话:";
cin >> phone;
m= name.length() % 7;
AddPerson(m,name,phone);
break;
case 2:
cout << "请输入要删除的联系人姓名:";
cin >> name;
m = name.length() % 7;
DeletePerson(m,name);
break;
case 3:
cout << "请输入要查找的联系人姓名:";
cin >> name;
m = name.length() % 7;
FindPersonname(m, name);
break;
case 4:
cout << "请输入要修改的联系人姓名:";
cin >> name;
cout << "请输入新的电话:";
cin >> newPhone;
m = name.length() % 7;
ChangePerson(m,name,newPhone);
break;
case 5:
AllPerson();
break;
case 6:
cout << "退出程序";
break;
default:
cout << "输入错误,请重新输入";
break;
}
}while (s != 6);
return NULL;
}
void AddPerson(int m, string name,string phone) {
Person* p = new Person;
p->name = name;
p->phone = phone;
cout << "添加成功!" << endl;
Person* temp = contacts[m];
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
menue(2);
}
void DeletePerson(int m, string name) {
int k = 1;
Person* root4 = contacts[m];
Person* root2 = contacts[m];
Person* root3 = contacts[m];
while (root4 != NULL) {
if (root4->name == name) {
root2 = root4->next;
delete root4;
root3->next = root2;
cout << "删除成功!" << endl;
k = 0;
break;
}
root3 = root4;
root4 = root4->next;
}
if (k == 1)
cout << "删除失败!" << endl;
menue(6);
}
void FindPersonname(int m,string name) {
Person* root = contacts[m];
while (root != NULL) {
if (root->name == name&&root!=NULL) {
cout << "姓名:" << root->name << " 电话:" << root->phone << endl;
cout << "查找成功!" << endl;
break;
}
root = root->next;
}
if (root == NULL)
cout << "查找失败!" << endl;
menue(3);
}
void ChangePerson(int m,string name,string newPhone) {
Person* root2 = contacts[m];
while (root2 != NULL) {
if (root2->name == name) {
root2->phone = newPhone;
cout << "修改成功!" << endl;
break;
}
root2 = root2->next;
}
if (root2 == NULL)
cout << "修改失败!" << endl;
menue(4);
}
void AllPerson() {
int i;
cout << "所有联系人信息:" << endl;
for (i = 0;i < 7;i++) {
Person* root2 = contacts[i]->next;
while (root2 != NULL) {
cout << "姓名:" << root2->name << " 电话:" << root2->phone << endl;
root2 = root2->next;
}
}
menue(5);
}
int main() {
int i;
for (i = 0;i < 7;i++) {
contacts[i] = new Person;
contacts[i]->next = NULL;
}
menue(1);
for (i = 0; i < 7;i++) {
Person* root = contacts[i];
while (root != NULL) {
Person* temp = root;
root = root->next;
delete temp;
}
}
return 0;
}
2.对A~Z取模,第一个字母必为字母
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Person
{
string name;
string phone;
struct Person* next = NULL;
};
vector<Person*> contacts(26);
void AddPerson(int m, string name, string phone);
Person* menue(int i);
void DeletePerson(int m, string name);
void FindPersonname(int m, string name);
void ChangePerson(int m, string name, string newPhone);
void AllPerson();
Person* menue(int i)
{
int s, m;
string name, newPhone, phone;
cout << "欢迎使用通讯录管理系统\n";
cout << "请选择接下来要做什么:\n1.添加联系人\n2.删除联系人\n3.通过姓名查找联系人\n4.修改联系人\n5.显示所有联系人\n6.退出程序\n请输入对应的数字:" << endl;
cin >> s;
do {
switch (s) {
case 1:
cout << "请输入姓名:";
cin >> name;
cout << "请输入电话:";
cin >> phone;
if (name.front() >= 'A' && name.front() <= 'Z') {
m = (name.front() - 'A') % 26;
}
else if (name.front() >= 'a' && name.front() <= 'z') {
m = (name.front() - 'a') % 26;
}
AddPerson(m, name, phone);
break;
case 2:
cout << "请输入要删除的联系人姓名:";
cin >> name;
if (name.front() >= 'A' && name.front() <= 'Z') {
m = (name.front() - 'A') % 26;
}
else if (name.front() >= 'a' && name.front() <= 'z') {
m = (name.front() - 'a') % 26;
}
DeletePerson(m, name);
break;
case 3:
cout << "请输入要查找的联系人姓名:";
cin >> name;
if (name.front() >= 'A' && name.front() <= 'Z') {
m = (name.front() - 'A') % 26;
}
else if (name.front() >= 'a' && name.front() <= 'z') {
m = (name.front() - 'a') % 26;
}
FindPersonname(m, name);
break;
case 4:
cout << "请输入要修改的联系人姓名:";
cin >> name;
cout << "请输入新的电话:";
cin >> newPhone;
if (name.front() >= 'A' && name.front() <= 'Z') {
m = (name.front() - 'A') % 26;
}
else if (name.front() >= 'a' && name.front() <= 'z') {
m = (name.front() - 'a') % 26;
}
ChangePerson(m, name, newPhone);
break;
case 5:
AllPerson();
break;
case 6:
cout << "退出程序";
break;
default:
cout << "输入错误,请重新输入";
break;
}
} while (s != 6);
return NULL;
}
void AddPerson(int m, string name, string phone) {
Person* p = new Person;
p->name = name;
p->phone = phone;
cout << "添加成功!" << endl;
Person* temp = contacts[m];
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
menue(2);
}
void DeletePerson(int m, string name) {
int k = 1;
Person* root4 = contacts[m];
Person* root2 = contacts[m];
Person* root3 = contacts[m];
while (root4 != NULL) {
if (root4->name == name) {
root2 = root4->next;
delete root4;
root3->next = root2;
cout << "删除成功!" << endl;
k = 0;
break;
}
root3 = root4;
root4 = root4->next;
}
if (k == 1)
cout << "删除失败!" << endl;
menue(6);
}
void FindPersonname(int m, string name) {
Person* root = contacts[m];
while (root != NULL) {
if (root->name == name && root != NULL) {
cout << "姓名:" << root->name << " 电话:" << root->phone << endl;
cout << "查找成功!" << endl;
break;
}
root = root->next;
}
if (root == NULL)
cout << "查找失败!" << endl;
menue(3);
}
void ChangePerson(int m, string name, string newPhone) {
Person* root2 = contacts[m];
while (root2 != NULL) {
if (root2->name == name) {
root2->phone = newPhone;
cout << "修改成功!" << endl;
break;
}
root2 = root2->next;
}
if (root2 == NULL)
cout << "修改失败!" << endl;
menue(4);
}
void AllPerson() {
int i;
cout << "所有联系人信息:" << endl;
for (i = 0;i < 26;i++) {
Person* root2 = contacts[i]->next;
while (root2 != NULL) {
cout << "姓名:" << root2->name << " 电话:" << root2->phone << endl;
root2 = root2->next;
}
}
menue(5);
}
int main() {
int i;
for (i = 0;i < 26;i++) {
contacts[i] = new Person;
contacts[i]->next = NULL;
}
menue(1);
for (i = 0; i < 26;i++) {
Person* root = contacts[i];
while (root != NULL) {
Person* temp = root;
root = root->next;
delete temp;
}
}
return 0;
}
三、实验使用环境
以下请根据实际情况编写
- 操作系统:Windows 11专业版
- 编程语言:C++
- 开发工具:[Visual Studio 2022]
四、实验步骤和调试过程
手机通讯录
1.顺序链表
本机运行截图
2.哈希法
本机运行截图
![]()
![]()
![]()
![]()
五、实验小结
遇到的问题及解决方法:
- 问题:创建的链表未正确处理,被覆盖
- 解决方法:优化代码,修改链表的传递方法
实验体会和收获:
哈希法(链地址法)平均情况下操作时间复杂度为 O((n+1)/2),但最坏情况下同样是 O(n),这里的n指在相同m下有多少个链表,这个链表节点数会小于等于总链表节点数,空间复杂度为O(n),这里的n会大于等于总链表节点数。顺序链表法每个函数所遍历的时间复杂度都为O(n),空间复杂度为O(n),这里的n是总链表节点数。综上所述,在平均情况下,哈希法(链地址法)在查找、插入和删除操作上的性能要优于链表法。